程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WPF中如何查找數據模板中的子元素

WPF中如何查找數據模板中的子元素

編輯:關於.NET

前兩天在寫一個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控件的結構看得清清楚楚,還可以看到各元素的屬性的實時值。

最後的結果。

怎麼樣,這個很實用吧。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved