[Silverlight]使用PagedCollectionView配合复选框实现动态筛选的解决方案
2009-12-12 23:43
621 查看
在之前的文章中提到,PagedCollection提供了筛选(Filter)功能。
实际项目中我们往往有这样的需求
即通过复选框动态的筛选DataGird的相关项,比如上面截图所示例的筛选Gender列特定项。有的朋友可能已经想到了:直接操作ObservableCollection不就行了吗?其实这样做存在两个问题:
PagedCollectionView本来就提供了筛选功能,操作ObservableCollection是不是显得有点蠢了?
操作ObservableCollection后(筛选的时候一般是移除项),集合本身也发生了变化,而PagedCollectionView提供的筛选只是在UI中反映变化而不会改变集合项
既然有如上两个问题,那么我们还是老老实实的使用PagedCollectionView的Filter属性实现筛选吧
不过依然是存在问题的,这个暂且不说,先看一下正常情况下我们要实现以上需求需要做的工作
首先要在XAML中添加四个复选框
将三个CheckBox一个StackPanel中除了布局需要外,还可以方便我们遍历出所有的CheckBox以便过滤操作。
接下来,我们需要在CheckBox_Click的cs代码中做如下工作
如果只有一个CheckBox(比如:男),我们可以简单的这样
可现在我们有N个CheckBox,鉴于PagedCollectionView的Filter又是一个Predicate<object>,所以我们只能这样(这里我们假设只有两个CheckBox的情况,因为实在是太麻烦了)
可见要是再多几个复选框,这些判断就要搞死人了。解决这个问题的关键就是动态构建Predicate,所以这里我们编写一个PredicateBuilder通过拼接表达式来辅助我们动态构建Predicate
代码比较简单,就不多解释了。注意最后的ConvertToPredicate<T>这个扩展方法用来将构建好的Expression编译后的Func<T,bool>转换为Predicate<T>。
有了这个类的辅助后,我们的CheckBox_Click事件可就既省事又优雅多了
到此为止问题解决,希望能对搞Sl企业级开发的兄弟们有所帮助
Okay,have fun~
实际项目中我们往往有这样的需求
即通过复选框动态的筛选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~
相关文章推荐
- WPF and Silverlight 学习笔记(二十五):使用CollectionView实现对绑定数据的排序、筛选、分组
- [转]WPF and Silverlight 学习笔记(二十五):使用CollectionView实现对绑定数据的排序、筛选、分组
- WPF and Silverlight 学习笔记(二十五):使用CollectionView实现对绑定数据的排序、筛选、分组
- Silverlight中如何自己写方法将DataTable转换为PagedCollectionView数据(动态创建类)
- 该篇博客是在《iOS高级开发——CollectionView的动态增删cell及模型重构》的基础上继续进行开发的。在之前那篇博客中,我们实现了动态的增删cell,并且使用了模型Model进行重构
- SilverLight:使用MVVM实现View层在程序运行时自动生成控件并且取得其值 (转)
- 使用Autolayout实现UITableView的Cell动态布局和高度动态改变
- ios TableView那些事(三十 五)TableView 单选操作使用Autolayout实现UITableView的Cell动态布局和高度动态改变
- 使用PagerTabStrip配合ViewPager实现左右滑动标题栏的效果
- Swift 使用CollectionView 实现图片轮播封装就是这样简单
- 使用CSStickyHeaderFlowLayout实现头部固定的CollectionView
- Android使用自定义View继承SurfaceView实现动态折线图的绘制
- Android编程心得-使用ActionBar+Fragment+ViewPager实现动态切换Menu效果
- 使用viewflipper实现左右滑动,动态切换view
- 使用Autolayout实现UITableView的Cell动态布局和高度动态改变
- 使用recyclerView,GridView来实现动态显示商品选择规格
- 使用Autolayout实现UITableView的Cell动态布局和高度动态改变
- Silverlight中的PagedCollectionView
- 使用Swift实现iOScollectionView广告无限滚动效果(DEMO)
- 使用Visifire+ArcGIS API for Silverlight实现Graphic信息的动态图表显示