2017-03-06 36 views
0

我在列表框中顯示圖像列表,每個圖像都有一個標題在它下面。數據是一個JSON數組,其中包含數組中的每個子對象的JObject。加快添加項目到列表框(後面的代碼或xaml綁定?)

列表框項目是一個堆棧面板,圖像和文本被插入堆棧面板,然後插入到列表框中作爲一個項目。

唯一的問題是它有很多數據很慢(40或更多的項目)。

我聽說XAML數據綁定速度要快得多,但我沒有運氣在屏幕上獲取任何東西。

XAML綁定是否會加快速度,因此可用?理想情況下,我希望它是即時或「流行」風格,其中每個項目都是可用的,而不鎖定程序。數據來自本地JSON文件和本地圖像。

如果可以在代碼背後完成,那麼很好。但我似乎無法提高速度。將它移到一個線程上也沒有任何邊際差異。

這裏是我如何通過後面的代碼添加項目:

// Loop through the data 
foreach (dynamic item in this.data.Select((value, i) => new { i, value })) 
{ 
    // Create the image for this item 
    this.images[item.i] = new Image 
    { 
     Width = 278, 
     Height = 178, 
    }; 

    // If the image for this item exists 
    if (File.Exists(item.value["Image"].ToString())) 
    { 
     // The path to this image 
     string imageFilePath = item.value["Image"].ToString(); 
     // Set the image source 
     this.images[item.i].Source = new BitmapImage(new Uri(imageFilePath, UriKind.RelativeOrAbsolute)); 
    } 

    // Create a stack panel to store our item 
    StackPanel stackPanel = new StackPanel 
    { 
     Width = 288, 
     Height = 215, 
    }; 

    // Create the items text 
    TextBlock textBlock = new TextBlock(); 
    textBlock.text = item.value["Text"].ToString(); 

    // Add the Image to the stack panel 
    stackPanel.Children.Add(this.images[item.i]); 
    // Add the text to the stack panel 
    stackPanel.Children.Add(textBlock); 

    // Add the stackpanel to the list 
    this.Items.Add(stackPanel); 
} 

窗口的XAML:

<Window x:Class="MyProject.Windows.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:MyProject" 
     mc:Ignorable="d" 
     Title="Window" Width="800" Height="600"> 

    <Grid> 
     <!-- The list box --> 
     <ListBox x:Name="listBox" /> 
    </Grid> 
</Window> 

這是XAML的,我試圖綁定列表框。它沒有出現在屏幕上。

編輯:如果我將後面的代碼移到一個方法中,並在我的代碼中某處調用該方法,它確實會導致我的圖像/文本出現在屏幕上。它最初並不這樣做,爲什麼?它也和版本背後的代碼一樣慢。

<ListBox x:Name="listBox" ItemsSource="{Binding testList}"> 
    <ListBox.ItemTemplate> 
     <DataTemplate> 
      <VirtualizingStackPanel> 
       <Image Source="{Binding Image}"/> 
       <TextBlock Text="{Binding Text}" FontSize="20" /> 
      </VirtualizingStackPanel> 
     </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

背後結合

// List to store our data 
private List<Item> testList { get; set; } 

public MyClass() 
{ 
    // Initialise the test list 
    this.testList = new List<Item>(); 
    // Loop through the data 
    foreach (dynamic item in this.data.Select((value, i) => new { i, value })) 
    { 
     Item item = item.value.ToObject<Item>(); 
     this.testList.Add(item); 
    } 

    this.ItemsSource = this.testList; 
} 

代碼爲XAML謝謝

+0

什麼是ToObject?在調用'ToObject'之前什麼類型是值? –

+0

ToObject是一個JSON.Net方法,可以在JObjects上調用它來將它們轉換爲特定的類型。在這種情況下,一個項目,它是一個包含兩個成員的類Image和Text – PersuitOfPerfection

回答

3

不要在代碼中創建您的控件後面。相反,使用ListBoxDataTemplateBindingItemTemplate。我試圖解釋,最好的辦法:

與這兩個屬性創建一個類:

public class Model : INotifyPropertyChanged 
{ 
    string _imageFilePath; 
    public string ImageFilePath { get { return _imageFilePath; } set { _imageFilePath = value; RaisePropertyChanged("ImageFilePath"); } } 

    string _text; 
    public string Text { get { return _text; } set { _text = value; RaisePropertyChanged("Text"); } } 

    public event PropertyChangedEventHandler PropertyChanged; 
    void RaisePropertyChanged(string propname) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propname)); 
    } 
} 

你最重要的工作應該是填充的ObservableCollection<Model>,通過你的數據循環。讓我們把這個集合在下面的類:

public class ViewModel 
{ 
    public ViewModel() 
    { 
     //populate the Models here 
    } 

    ObservableCollection<Model> _models; 
    public ObservableCollection<Model> Models { get { return _models; } set { _models = value; } } 

} 

使用

<ListBox ItemsSource="{Binding Models}"> 
<ListBox.ItemTemplate> 
    <DataTemplate> 
     <StackPanel> 
      <Image Source="{Binding ImageFilePath }"/> 
      <TextBlock Text="{Binding Text}" FontSize="20" /> 
     </StackPanel> 
    </DataTemplate> 
</ListBox.ItemTemplate> 
</ListBox> 

爲其DataContext設置propertly:

public MainWindow() 
{ 
    DataContext = new ViewModel(); 
    InitializeComponent(); 
} 

這應該工作。

+0

您並不需要爲ListBox指定'DataContext'。特別是因爲'DataContext = {Binding}'只是將'DataContext'綁定到它自己。 –

+1

謝謝。你是對的。這只是一種習慣。 – Ron

+0

謝謝你,我看到你的代碼與我嘗試的代碼相比有些不同。我會給這個旋轉和回報 – PersuitOfPerfection

相關問題