0

当我ListBox在启用虚拟化的情况下创建然后更新其所有项目外观时,它的工作速度非常快。但是当我慢慢向下滚动所有项目ListBox然后更新所有项目的外观时,它需要很多时间。我认为这是因为VirtualizingStackPanel当它们用完视口时不会破坏它们。我编写了简单的应用程序来重现这种行为。

代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        for(int i = 0; i < 5000; ++i) // creating 5k text boxes
            MyList.Items.Add(new TextBox() { Text = CurrText });
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        GC.Collect();
        n = (n + 1) % 2; // switch 0 to 1 or 1 to 0
        foreach (var item in MyList.Items)
            ((TextBox)item).Text = CurrText; // set new text
    }

    static int n = 0;
    string CurrText { get { return new string(n.ToString()[0], 50); } }
}

XAML:

<Window x:Class="VPanel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="700" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="5*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <ListBox Name="MyList" VirtualizingStackPanel.IsVirtualizing="True"/>
        <Button Grid.Row="1" Content="UpdateText" Click="Button_Click"/>
    </Grid>
</Window>

单击“UpdateText”按钮更新所有文本框文本。如果通过拖动滚动条慢慢滚动到结束,“UpdateText”按钮会出现巨大的延迟。

4

1 回答 1

0

不要TextBoxes手动创建。

“虚拟化”一词是指一种技术,通过该技术,用户界面 (UI) 元素的子集根据哪些项目在屏幕上可见而从大量数据项目中生成。当屏幕上可能只有几个元素时生成许多 UI 元素会对应用程序的性能产生不利影响

您手动创建 UI 项,因此对于虚拟化来说已经太迟了。使用绑定,它将TextBoxItemTemplate需要时创建。如果当前不在视图中,它也不会刷新TextBox.Text值。为此,请更改您MainWindow的创建ObservableCollection而不是TextBoxes对其进行操作:

public partial class MainWindow : Window
{
    private readonly ObservableCollection<string> _textBoxes = new ObservableCollection<string>();

    public ICollection<string> TextBoxes { get { return _textBoxes; } }

    private int n = 0;
    private string CurrText { get { return new string(n.ToString()[0], 50); } }

    public MainWindow()
    {
        for (int i = 0; i < 5000; ++i) _textBoxes.Add(CurrText);
        InitializeComponent();
        DataContext = this;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        n = (n + 1) % 2; // switch 0 to 1 or 1 to 0
        for (int i = 0; i < _textBoxes.Count; i++) _textBoxes[i] = CurrText;
    }
}

然后将 XAML 更改为绑定到TextBoxes列表属性

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="5*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <ListBox ItemsSource="{Binding TextBoxes}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBox Text="{Binding Path=., Mode=TwoWay}"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <Button Grid.Row="1" Content="UpdateText" Click="Button_Click"/>
</Grid>
于 2014-05-10T09:31:42.837 回答