具有相同视觉树的ListBox的不同性能和SelectedItem [英] Different perfomance and SelectedItem of ListBox having the same visual tree

查看:64
本文介绍了具有相同视觉树的ListBox的不同性能和SelectedItem的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用ListBox创建了测试WPF应用程序.我用100000个文件名(字符串)填充它.目的是通过SelectedItem属性从用户的选择中检索ListBoxItem对象.但是,事情并非如此简单.属性SelectedItem返回不同 用不同方式填充ListBox时的对象.所以,这是代码.

I have created test WPF application with ListBox. I fill it with 100000 file names (string). The goal is to retrieve ListBoxItem object from user's selection by SelectedItem property. However, not is all that simple. The property SelectedItem returns different objects when filling ListBox with different ways. So, here's code.

#define USE_VISUAL_TREE

namespace WPFTest
{
    enum FileTest
    {
        ItemsSource,
        ForEachAddString,
        ForEachAddListBoxItem
    }

    public partial class Test : Window
    {
        FileTest test;

        string folder = Path.Combine(Directory.GetCurrentDirectory(), "A lot of files");

        private void ShowFiles(object sender, RoutedEventArgs e)
        {
            listBox.ItemsSource = null;
            listBox.Items.Clear();
            var files = Directory.EnumerateFiles(folder);

            switch (cmbTest.SelectedIndex)
            {
                case 0: //Way 1: The fastest way - immediately
                {
                    test = FileTest.ItemsSource;
                    listBox.ItemsSource = files;
                    break;
                }
                case 1: //Way 2: Takes 1 second more than Way 1
                {
                    test = FileTest.ForEachAddString;
                    files.ForEach(f => listBox.Items.Add(f));
                    break;
                }
                case 2: //Way 3: The slowest way
                {
                    test = FileTest.ForEachAddListBoxItem;
                    files.ForEach(f => listBox.Items.Add(new ListBoxItem { Content = f }));
                    break;
                }
            }
        }

        object GetElementInVisualTree(DependencyObject obj, int[] indexes)
        {
            for (int i = 0; i <= indexes.GetUpperBound(0); i++)
                obj = VisualTreeHelper.GetChild(obj, indexes[i]);
            return obj;
        }

        private void OnListBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            object element;
            ListBox list = (ListBox)sender;

#if USE_VISUAL_TREE
            int index = list.SelectedIndex;
            element = GetElementInVisualTree(list, indexes: new int[] { 0, 0, 0, 1, 0, 0, index });
#else
            element = list.SelectedItem;
#endif
            ListBoxItem item = element as ListBoxItem;
            if (item != null)
            {
                Title = item.Content.ToString();
            }

        }

    }

    internal static class StringExtensions
    {
        internal static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
        {
            var enumerator = enumerable.GetEnumerator();
            while (enumerator.MoveNext())
                action(enumerator.Current);
        }
    }

}

问题在于,当使用ItemsSource(方法1)并使用带有填充字符串的ForEach(方法2)时,SelectedItem返回String.直接添加ListBoxItem(方法3)填充ListBox可以正确提供ListBoxItem.可以说那又怎样?只需添加ListBoxItem 直接地.怎么了?".这就是为什么我创建了这么多文件-测试每种方式的速度的原因.我所拥有的:

The problem is that SelectedItem returns String when using ItemsSource (Way 1) and using ForEach with filling strings (Way 2). Filling ListBox with direct adding ListBoxItem (Way 3) correctly gives ListBoxItem. One can say that "So, what? Just add ListBoxItem directly. What's wrong with it?". That is why I created so many files - to test the speed of each way. What I have got:

1)ItemsSource是最快的方法-几乎立即可以实现.

1) ItemsSource is the fastest way - almost immediately.

2)带有字符串的ForEach比ItemsSource多花费1秒.

2) ForEach with adding string takes 1 second more than ItemsSource.

3)最慢的是直接添加ListBoxItem-耗时7秒.

3) The slowest is adding ListBoxItem directly - it takes 7 seconds.

尽管用户拥有100000个文件的机会微乎其微,但无论如何,它的速度要慢700%.

Although the chances that a user will have 100000 files are slim to none, anyway it's 700% slower.

这是ListBox的主要怪异行为-三种方式的可视树都是相同的!以下是所有三棵视觉树的屏幕截图(由于限制而无法上传第三张屏幕截图,但相同):

And here's the main weird behavior of ListBox - the visual tree for all three ways is THE SAME! Here are screen shots of all three visual trees (can't upload third screenshot because of limitation, but it is the same):


通过调用SelecteItem属性返回的每种方式:

What each way returns by invoking SelecteItem property:

1)方法1(ItemsSource)-返回字符串.

1) Way 1 (ItemsSource) - returns String.

2)方法2(添加字符串的ForEach)-返回 String .

2) Way 2 (ForEach with adding string) - returns String.

3)方法3(添加了ListBoxItem的ForEach)-返回 ListBoxItem .

3) Way 3 (ForEach with adding ListBoxItem) - returns ListBoxItem.

因此,如果我选择ItemsSource,则必须以某种方式检索ListBoxItem.我发现的方法是遍历视觉树( GetElementInVisualTree 方法).这不是理想的方式.

So, if I choose ItemsSource, then I have to retrieve ListBoxItem someway. The way I have found is traversing visual tree (GetElementInVisualTree method). It is not the desired way.

摘要: ListBox为每种方式创建一个相同的可视树,同时这些方式在加快速度并返回SelectedItem中的其他对象!

SUMMARY: ListBox creates one and the same visual tree for each way, and at the same time these ways are different in speed and return different object in SelectedItem!

有人能解释这种奇怪的行为吗?

Can anyone explain such weird behavior?

没有知识就是力量.

推荐答案

SelectedItem属性返回已设置为ItemSource的数据对象的类型.或在ListBox.Add方法中.因此,它在方法3中返回ListBoxItem,并在方法1&中返回字符串. 2. 在方法3中,您将为每个 文件创建一个新的ListBoxItem实例. 与直接设置String集合相比,创建ListBoxItem 10000次显然要花费更多时间.

SelectedItem property returns the type of data object which you have set as ItemSource or in ListBox.Add method. So it returns ListBoxItem in Way 3 and string in Way 1 & 2.   In Way 3 you are creating a new ListBoxItem instance for each  file and creation of ListBoxItem 10000 times would obviously take more time compared to directly setting a String collection.

创建ListBoxItem对象是否有任何特定原因?如果与格式化列表框中的数据有关,则最好设置 ListBox .ItemTemplate 属性

Is there any specific reason you are creating ListBoxItem object? If it is related to formatting the data in listbox then you should better set ListBox.ItemTemplate property 


这篇关于具有相同视觉树的ListBox的不同性能和SelectedItem的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆