加快将项目添加到列表框(代码隐藏或xaml绑定?)

时间:2017-03-06 19:52:59

标签: c# wpf listbox json.net

我在列表框中显示图像列表,每个图像下面都有一个标题。数据是一个JSON数组,其中包含数组中每个子节点的JObject。

列表框项目是一个堆栈面板,图像和文本将插入到堆栈面板中,然后将其作为项目插入到列表框中。

唯一的问题是它有很多数据(40个或更多项)很慢。

我听说XAML数据绑定速度要快得多,但屏幕上没有任何运气。

XAML绑定会加快速度吗?它可以使用吗?理想情况下,我希望它是即时的,或者#34; pop in"每个项目在可用时添加的样式,而不会锁定程序。数据来自本地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);
}

The Window的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>

这是我尝试绑定的ListBox的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>

XAML绑定背后的代码

// 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;
}

谢谢

1 个答案:

答案 0 :(得分:3)

不要在代码背后创建控件。相反,请使用BindingItemTemplate的{​​{1}}和ListBox。我试着解释最好的方法:

使用以下两个属性创建一个类:

DataTemplate

您最重要的工作应该是通过循环浏览数据来填充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; } }

}

为DataContext设置属性:

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

这应该有用。