[Silverlight]使用PagedCollectionView配合复选框实现动态筛选的解决方案

简介:


之前的文章中提到,PagedCollection提供了筛选(Filter)功能。

实际项目中我们往往有这样的需求

image

即通过复选框动态的筛选DataGird的相关项,比如上面截图所示例的筛选Gender列特定项。有的朋友可能已经想到了:直接操作ObservableCollection不就行了吗?其实这样做存在两个问题:

  • PagedCollectionView本来就提供了筛选功能,操作ObservableCollection是不是显得有点蠢了?
  • 操作ObservableCollection后(筛选的时候一般是移除项),集合本身也发生了变化,而PagedCollectionView提供的筛选只是在UI中反映变化而不会改变集合项

既然有如上两个问题,那么我们还是老老实实的使用PagedCollectionView的Filter属性实现筛选吧

不过依然是存在问题的,这个暂且不说,先看一下正常情况下我们要实现以上需求需要做的工作

首先要在XAML中添加四个复选框

<StackPanel Orientation="Horizontal" x:Name="cbContainer">
     <CheckBox Content="男" IsChecked="True"  Click="CheckBox_Click"/>
     <CheckBox Content="女" IsChecked="True"  Click="CheckBox_Click" />
     <CheckBox Content="无" IsChecked="True"  Click="CheckBox_Click" />
</StackPanel>

将三个CheckBox一个StackPanel中除了布局需要外,还可以方便我们遍历出所有的CheckBox以便过滤操作。

接下来,我们需要在CheckBox_Click的cs代码中做如下工作

如果只有一个CheckBox(比如:男),我们可以简单的这样

string genderToFilter = ((CheckBox)sender).Content.ToString();
_pcv.Filter = p => ((Person)p).Gender == genderToFilter;

可现在我们有N个CheckBox,鉴于PagedCollectionView的Filter又是一个Predicate<object>,所以我们只能这样(这里我们假设只有两个CheckBox的情况,因为实在是太麻烦了)

  var els = cbContainer.Children;
            var cb1 = els[0] as CheckBox;
            var cb2 = els[1] as CheckBox;

            Predicate<object> predicate;
            if (cb1.IsChecked == true || cb2.IsChecked == false) {
                predicate = p => ((Person)p).Gender == cb1.Content.ToString();
            }
            else if (cb1.IsChecked == true || cb2.IsChecked == false) {
                predicate = p => ((Person)p).Gender == cb1.Content.ToString() || ((Person)p).Gender == cb2.Content.ToString();
            }
            else {
                predicate = p => ((Person)p).Gender == cb2.Content.ToString();
            }

            _pcv.Filter = predicate;

可见要是再多几个复选框,这些判断就要搞死人了。解决这个问题的关键就是动态构建Predicate,所以这里我们编写一个PredicateBuilder通过拼接表达式来辅助我们动态构建Predicate

public static class PredicateBuilder {
        public static Expression<Func<T, bool>> True<T>() { return f => true; }
        public static Expression<Func<T, bool>> False<T>() { return f => false; }

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
                                                            Expression<Func<T, bool>> expr2) {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
        }

        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
                                                             Expression<Func<T, bool>> expr2) {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>
                  (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
        }

        public static Predicate<T> ConvertToPredicate<T>(this Func<T, bool> func) {
            return new Predicate<T>(func);
        }
    }

代码比较简单,就不多解释了。注意最后的ConvertToPredicate<T>这个扩展方法用来将构建好的Expression编译后的Func<T,bool>转换为Predicate<T>。

有了这个类的辅助后,我们的CheckBox_Click事件可就既省事又优雅多了

        private void CheckBox_Click(object sender, RoutedEventArgs e) {
            var els = cbContainer.Children;
            var predicate = PredicateBuilder.False<object>();
            foreach (var el in els) {
                var cb = el as CheckBox;
                if (cb.IsChecked == true) {
                    predicate = predicate.Or(p => ((Person)p).Gender == cb.Content.ToString());
                }
            }
            _pcv.Filter = predicate.Compile().ConvertToPredicate<object>();
        }

到此为止问题解决,希望能对搞Sl企业级开发的兄弟们有所帮助

Okay,have fun~














本文转自紫色永恒51CTO博客,原文链接:http://www.cnblogs.com/024hi/archive/2009/12/12/1622795.html ,如需转载请自行联系原作者



相关文章
|
JavaScript C#
一起谈.NET技术,WPF/Silverlight深度解决方案:目录
  介于目前WPF/Silverlight技术资料在国内相当稀缺,仅有的也是一些很基础的教程。为了更深度的剖析WPF/Silverlight的技术内涵,解决开发过程中的疑难杂症,分解实际应用案例的特色细节,“WPF/Silverlight深度解决方案”系列由此孕育而生。
1307 0
一起谈.NET技术,Silverlight 2.5D RPG游戏技巧与特效处理:(三)动态光影
  通常来说,只要谈到影子及影子制作,首先想到的不外乎3D。游戏中的影子设计大致可分为硬实现和软实现两种,比如像“游戏影子制作技术”这篇文章所谈到3D游戏影子制作方案Projective Shadow、Shadow Map以及Shadow Volume均属于硬实现。
1158 0

热门文章

最新文章