C# WPF 父控件通過使用可視化樹找到子控件的示例代碼
在我們使用WPF設(shè)計前臺界面時,經(jīng)常會重寫數(shù)據(jù)模板,或者把控件放到數(shù)據(jù)模板里。但是一旦將控件放到數(shù)據(jù)模板中,在后臺就沒有辦法通過控件的名字來獲取它了,更沒辦法對它進行操作(例如,隱藏,改變控件的某個值)。
如果你是比我還白的小白,對我剛剛陳述的東西不清楚,接下來我簡單說一下什么是把控件放在數(shù)據(jù)模板中,怎么樣的情況沒法后臺通過名字來獲取控件,如果讀者對于數(shù)據(jù)模板這些事兒已經(jīng)清楚了,或者只關(guān)心如何使用可視化樹可以將這部分跳過哈。
先上代碼介紹一下什么是數(shù)據(jù)模板以WPF中ListBox控件為例:
<ListBox Name="ListBox_1" HorizontalAlignment="Left" Height="299" Margin="10,10,0,0" VerticalAlignment="Top" Width="497" MouseDoubleClick="ListBox_1_OnMouseDoubleClick"> <ListBox.ItemTemplate> <DataTemplate> <Button Name="Button_1" Content="666"></Button> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
我在后臺設(shè)置了顯示了8行item,效果如下:
我們可以看到重寫數(shù)據(jù)模板實現(xiàn)的效果是在ListBox的每一項Item都是一個Button,這里介紹的只是一些簡單應(yīng)用例子,重寫模板是很強大的。因為如果用到可視化樹多半是因為使用了數(shù)據(jù)模板在后臺用名字無法找到相應(yīng)控件了,所以在此簡單介紹一下,方便理解。
接下來我們在后臺嘗試通過控件的名字來找到我們的ListBox和Button
我們發(fā)現(xiàn)通過控件的名字可以找到ListBox但是通過button的名字卻無法找到button,這就是數(shù)據(jù)模板搞的鬼。
但是沒有關(guān)系,我們可以通過可視化樹從ListBox里找到它的子控件我們想要的這個Button。
重點來了,先上代碼,可視化樹通過父控件找到它的子控件:
List<T> FindVisualChild<T>(DependencyObject obj) where T : DependencyObject { try { List<T> list = new List<T>(); for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { DependencyObject child = VisualTreeHelper.GetChild(obj, i); if (child is T) { list.Add((T)child); List<T> childOfChildren = FindVisualChild<T>(child); if (childOfChildren != null) { list.AddRange(childOfChildren); } } else { List<T> childOfChildren = FindVisualChild<T>(child); if (childOfChildren != null) { list.AddRange(childOfChildren); } } } return list; } catch (Exception) { //MessageBox.Show(ee.Message); return null; } }
先將上面的方法復(fù)制到你的項目當(dāng)中,此時對于可視化樹的應(yīng)用已經(jīng)完成一半了。
接下來上代碼,通過可視化樹雙擊ListBox的ltem把對應(yīng)的button的Content值從666改成777:
private void ListBox_1_OnMouseDoubleClick(object sender, MouseButtonEventArgs e) { ListBoxItem myListBoxItem = (ListBoxItem)ListBox_1.ItemContainerGenerator.ContainerFromItem(ListBox_1.SelectedItem); List<Button> btnList = FindVisualChild<Button>(myListBoxItem); foreach (var item in btnList) { item.Content = "777"; } }
效果就是雙擊哪個item哪個item中的button從666變成了777。
我們通過父控件找到了里面的子控件button,我們便可以對它進行任何操作(和用名字找到是一樣的)。
以上關(guān)于可視化樹的代碼可以應(yīng)用于ListBox,DataGrid,ListView,TreeView,對于“.ItemContainerGenerator.ContainerFromItem”這段代碼的含義我暫時不是很理解,歡迎指教和交流。
通過以上的例子相信讀者已經(jīng)可以使用可視化樹找到相應(yīng)的控件了,但在我的開發(fā)過程中曾遇到過一些問題,和對于使用可視化樹的一點小建議。
1.如果你在使用可視化樹執(zhí)行“ListBoxItem myListBoxItem = (ListBoxItem)ListBox_1.ItemContainerGenerator.ContainerFromItem(ListBox_1.SelectedItem);”這句返回值是空(實際上不是空),可能是因為界面沒有初始化完畢,我的理解是,在前臺這個控件還沒生成完畢,或者是你修改了值但前臺還沒有修改,可以加上這句:
控件名.UpdateLayout();
之后在使用可視化樹,這一條的說法和形容可能有點不嚴(yán)謹(jǐn),歡迎指正交流。
2.可視化樹使用的是遞歸的方法,所以它的效率不是很高,如果在程序中大量使用可視化樹,會使得程序變慢的。
3.調(diào)用可視化樹返回的列表如果沒有找到相應(yīng)的控件或是異常便會返回空值,所以建議在你遍歷可視化樹返回的列表時,請先判斷否非為空。
補充:WPF查找子控件和父控件方法
一、查找某種類型的子控件,并返回一個List集合 public List<T> GetChildObjects<T>(DependencyObject obj, Type typename) where T : FrameworkElement { DependencyObject child = null; List<T> childList = new List<T>(); for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++) { child = VisualTreeHelper.GetChild(obj, i); if (child is T && (((T)child).GetType() == typename)) { childList.Add((T)child); } childList.AddRange(GetChildObjects<T>(child,typename)); } return childList; } 調(diào)用: List<Button> listButtons = GetChildObjects<Button>(parentPanel, typeof(Button)); //parentPanel就是xaml里定義的控件的x:name 二、通過名稱查找子控件,并返回一個List集合 public List<T> GetChildObjects<T>(DependencyObject obj, string name) where T : FrameworkElement { DependencyObject child = null; List<T> childList = new List<T>(); for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++) { child = VisualTreeHelper.GetChild(obj, i); if (child is T && (((T)child).GetType() == name |string.IsNullOrEmpty(name))) { childList.Add((T)child); } childList.AddRange(GetChildObjects<T>(child,name)); } return childList; } 調(diào)用: List<Button> listButtons = GetChildObjects<Button>(parentPanel, "button1"); 三、通過名稱查找某子控件: public T GetChildObject<T>(DependencyObject obj, string name) where T : FrameworkElement { DependencyObject child = null; T grandChild = null; for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++) { child = VisualTreeHelper.GetChild(obj, i); if (child is T && (((T)child).Name == name | string.IsNullOrEmpty(name))) { return (T)child; } else { grandChild = GetChildObject<T>(child, name); if (grandChild != null) return grandChild; } } returnnull; } 調(diào)用: StackPanel sp = GetChildObject<StackPanel>(this.LayoutRoot, "spDemoPanel"); 四、通過名稱查找父控件 public T GetParentObject<T>(DependencyObject obj, string name) where T : FrameworkElement { DependencyObject parent = VisualTreeHelper.GetParent(obj); while (parent != null) { if (parent is T && (((T)parent).Name == name | string.IsNullOrEmpty(name))) { return (T)parent; } parent = VisualTreeHelper.GetParent(parent); } returnnull; } 調(diào)用: Grid layoutGrid = VTHelper.GetParentObject<Grid>(this.spDemoPanel, "LayoutRoot");
總結(jié)
以上所述是小編給大家介紹的C# WPF 父控件通過使用可視化樹找到子控件,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對我們網(wǎng)站的支持!
上一篇:C#實現(xiàn)Nginx平滑加權(quán)輪詢算法
欄 目:C#教程
下一篇:C#實現(xiàn)上傳下載圖片
本文標(biāo)題:C# WPF 父控件通過使用可視化樹找到子控件的示例代碼
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/5107.html
您可能感興趣的文章
- 01-10C#搜索TreeView子節(jié)點,保留父節(jié)點的方法
- 01-10C#實現(xiàn)子窗體與父窗體通信方法實例總結(jié)
- 01-10C#及WPF獲取本機所有字體和顏色的方法
- 01-10C#簡單實現(xiàn)子窗體向父窗體傳值的方法
- 01-10C#實現(xiàn)ComboBox控件顯示出多個數(shù)據(jù)源屬性的方法
- 01-10WPF實現(xiàn)類似360安全衛(wèi)士界面的程序源碼分享
- 01-10C#實現(xiàn)讀取DataSet數(shù)據(jù)并顯示在ListView控件中的方法
- 01-10WPF實現(xiàn)時鐘特效
- 01-10超炫酷的WPF實現(xiàn)Loading控件效果
- 01-10C#實現(xiàn)多選項卡的瀏覽器控件


閱讀排行
本欄相關(guān)
- 01-10C#通過反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻播放器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機閱讀
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-11ajax實現(xiàn)頁面的局部加載
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10delphi制作wav文件的方法
- 01-10C#中split用法實例總結(jié)
- 08-05織夢dedecms什么時候用欄目交叉功能?