[WPF]搜索列表项的四种实现方案点评
现在很多程序都提供了搜索功能。比如MSN的Search Contract,VS和Blend里的Property Search。一般是从一个比较大的,用户不太方便查找的列表中按关键字搜索符合条件的项目。如下图所示。
下面就来介绍一下这个功能在WPF中的实现。对WPF的类库功能不太熟悉的人可能会想到下面几个解决方案。
1. 根据关键字,对List绑定到的数据源进行修改,把不符合关键字的数据项暂时移出列表。这个就不评价了,入门选手的方案。性能和代码量都能让你瞠目结舌。
2. 上面的移出列表不太好?那就不移走了,把不想看到的Item的Visibility设置成Collapsed不就行了?这是个学院派的方案,遇到一个问题解决一个,而且看上去又是那个的合情理。但是,这个要如何实现呢?不要指望直接去设置Item的Visibility,因为控件上的顺序和数据上的顺序不一定相同。那你就要把Visibility绑定吧。那就要到数据上加个IsMatched属性吧。好了,现在每个Item都多了一个属性和一个绑定。
3. 使用Converter过滤,ConverterParameter作为关键字。多完美啊,多么具有新创意识啊。这个是东方不败式的方案。微软也不是吃干饭的,如果这个Convert真是万金油似的,它就不叫Converter了。如果没有问题也就罢了,可这个方案的确是有问题的。问题如下。
a. Converter的返回值是一个新的List,而不是你本来打算绑定到的那个List了。也就是说ListBox的ItemsSource将绑定到一个在Converter中生成的List中。如果哪天你想得到这个List,好么,去Converter里找吧。它和Data Model根本不在一层。这时你有两个选择,要么破坏软件的层次结构,要么用其它方案重写这个功能。
b. 性能问题,笔者所在的项目就在用这个方法。当项目数超过3000时,性能就已经让人无法忍受了。这时其实用数据绑定的角度,你没得解决方案,无论开启数据绑定的异步功能,还是自己用BackgroundWorker异步,都不能达到想要的效果。
当然,如果你的项目,使用Converter完全可以满足你的要求,而且你也已经把Converter用得如火纯青,那就用吧,一点问题也没有。笔者所在项目现在就在用这个方法,因为“它可以工作,那就别去动它。”
好了,现在就来介绍目前笔者所能找到的最佳方案——使用CollectionViewSource的Filter事件,在事件处理函数中你会得到要处理的一个Item,然后你来决定这个Item是不是要显示在界面上。这个方案是使用微软内置的功能实现的,也就是说微软第一次发布WPF的时候,就已经预见到了类似的需求并提供了支持,而且在他的官方示例中也演示了一翻。所心两年前就已经有人解释过个方案(有时要FQ)就不足为奇了。
笔者写了一个示例程序,即使用6000项字符串数据进行测试,速度还是很快的。
工作时常常会遇到这样的情况,要实现一个功能时,有时一下子就能想到很多个方案出来。然后就直接着手开始写代码,写着写着才发现吃力不讨好。其实这不是努力工作,而是犯懒的表现。因为评估多个解决方案从而找出最佳方案,或是研究一个功能的Best Practice是更需要脑力的。用第一感觉写代码,其实只是一种纯粹的体力劳动,而且不会有什么提高。“懒惰是程序员的第一美德”,但是要知道什么才是懒惰呢?