前兩天在寫一個WPF程序時,突然發現DataGrid控件沒有篩選功能,但我不急,因為我知道,WPF的好處在於UI與邏輯的分離,要給數據網格控件加上輸入篩選功能並不復雜,也不用去找第六方控件了,直接從DataGrid類派生一個類,並重定義它的控件模板,在DataGrid原有的控件模板上加一個StackPanel就可以了,方向為水平排列,放在列標頭的下方。然後在代碼中根據各個列的情況,向那個StackPanel添加N個文本框就可以輸入篩選信息了。呵呵,雖不算完美,解決燃眉之急還是可以的。
這樣我就想到另一個問題,如何修改DataTemplate裡面的元素呢。或者說如何獲取指定的元素。
於是,我在心裡產生了兩個方案:
1、在定義DataTemplate時,比如我裡面用了一個TextBlock控件,我給它命名為tbText,然後我就循環訪問集合控件的各個項,並得到每個項容器的ContentTemplate對象,希望用FindName方法直接把TextBlock取出來,但發生異常,這種方法不行。注意,如果DataTemplate定義在資源中,不能直接修改資源中的內容,因為這一改,會導致所有項都變了,因為集合控件(如ListBox)中每個項引用的都是同一個資源,而我現在要的是每個項裡面的TextBlock的前景色都不一樣。
2、我想到VisualTreeHelper類,對,就直接從項容器(ListBoxItem)的層次入手,一層一層往下找,直到找到TextBlock為止,由於我的模板中只有一個TextBlock,我就不必管它叫什麼名字,只要是TextBlock類型就可以。但因為裡面元素層次較多,不可能第一輪就能找到TextBlock,於是我寫了一個遞歸方法,把元素的所有子元素都翻了個遍。
// 已修正 private void FindChildByType(DependencyObject relate, Type type, ref FrameworkElement resElement) { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(relate); i++) { var el = VisualTreeHelper.GetChild(relate, i) as FrameworkElement; if (el.GetType() == type) { resElement = el; return; } else { FindChildByType(el, type, ref resElement); } } }
嘿嘿,這方法還果然驟效,為了使每個項的文本顏色不同,我使用了用隨機數來創建顏色。
private Color BuildColor() { Array.Clear(colorBs, 0, colorBs.Length); rand.NextBytes(colorBs); return Color.FromRgb(colorBs[0], colorBs[1], colorBs[2]); }
好了,現在可以動手去改變DataTemplate中的元素的屬性了。
/* 已修正 */
private void Button_Click_1(object sender, RoutedEventArgs e) { foreach (var item in lb.Items) { var el = lb.ItemContainerGenerator.ContainerFromItem(item) as FrameworkElement; if (el != null && el is ListBoxItem) { ListBoxItem lbItem = el as ListBoxItem; FrameworkElement efind = default(FrameworkElement); FindChildByType(lbItem, typeof(TextBlock), ref efind); if (efind is TextBlock) { TextBlock textblock = efind as TextBlock; textblock.Foreground = new SolidColorBrush(BuildColor()); } } } }
把每個項的TextBlock找出來,修改它的Foreground屬性。
我們可以在找到TextBlock後的代碼上下一個斷點,然後調試運行。代碼執行到斷點處停下,把鼠標移到TextBlock變量上,點擊名字右邊的放大鏡圖標,從彈出的菜單中選擇【WPF Tree Visualizer】。如下圖所示。
接著會彈出一個很好玩的窗口,在這個窗口中,你可以把WPF控件的結構看得清清楚楚,還可以看到各元素的屬性的實時值。
最後的結果。
怎麼樣,這個很實用吧。