[Silverlight]使用PagedCollectionView配合复选框实现动态筛选的解决方案
在之前的文章中提到,PagedCollection提供了篩選(Filter)功能。
實際項目中我們往往有這樣的需求
即通過復選框動態的篩選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~
轉載于:https://www.cnblogs.com/024hi/archive/2009/12/12/1622795.html
總結
以上是生活随笔為你收集整理的[Silverlight]使用PagedCollectionView配合复选框实现动态筛选的解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 高效管理ASP.NET的JavaScri
- 下一篇: DevExpress.XtraGrid.