C# WPF 父控制項通過使用可視化樹找到子控制項

来源:https://www.cnblogs.com/hellohxs/archive/2018/08/24/9528408.html
-Advertisement-
Play Games

在我們使用WPF設計前臺界面時,經常會重寫數據模板,或者把控制項放到數據模板里。但是一旦將控制項放到數據模板中,在後臺就沒有辦法通過控制項的名字來獲取它了,更沒辦法對它進行操作(例如,隱藏,改變控制項的某個值)。 如果你是比我還白的小白,對我剛剛陳述的東西不清楚,接下來我簡單說一下什麼是把控制項放在數據模板中 ...


在我們使用WPF設計前臺界面時,經常會重寫數據模板,或者把控制項放到數據模板里。但是一旦將控制項放到數據模板中,在後臺就沒有辦法通過控制項的名字來獲取它了,更沒辦法對它進行操作(例如,隱藏,改變控制項的某個值)。

如果你是比我還白的小白,對我剛剛陳述的東西不清楚,接下來我簡單說一下什麼是把控制項放在數據模板中,怎麼樣的情況沒法後臺通過名字來獲取控制項,如果讀者對於數據模板這些事兒已經清楚了,或者只關心如何使用可視化樹可以將這部分跳過哈。

先上代碼介紹一下什麼是數據模板以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>

我在後臺設置了顯示了8行item,效果如下:

我們可以看到重寫數據模板實現的效果是在ListBox的每一項Item都是一個Button,這裡介紹的只是一些簡單應用例子,重寫模板是很強大的。因為如果用到可視化樹多半是因為使用了數據模板在後臺用名字無法找到相應控制項了,所以在此簡單介紹一下,方便理解。

接下來我們在後臺嘗試通過控制項的名字來找到我們的ListBox和Button

我們發現通過控制項的名字可以找到ListBox但是通過button的名字卻無法找到button,這就是數據模板搞的鬼。

但是沒有關係,我們可以通過可視化樹從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;
            }
        }

先將上面的方法複製到你的項目當中,此時對於可視化樹的應用已經完成一半了。

接下來上代碼,通過可視化樹雙擊ListBox的ltem把對應的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,我們便可以對它進行任何操作(和用名字找到是一樣的)。

以上關於可視化樹的代碼可以應用於ListBox,DataGrid,ListView,TreeView,對於“.ItemContainerGenerator.ContainerFromItem”這段代碼的含義我暫時不是很理解,歡迎指教和交流。

通過以上的例子相信讀者已經可以使用可視化樹找到相應的控制項了,但在我的開發過程中曾遇到過一些問題,和對於使用可視化樹的一點小建議。

1.如果你在使用可視化樹執行“ListBoxItem myListBoxItem = (ListBoxItem)ListBox_1.ItemContainerGenerator.ContainerFromItem(ListBox_1.SelectedItem);”這句返回值是空(實際上不是空),可能是因為界面沒有初始化完畢,我的理解是,在前臺這個控制項還沒生成完畢,或者是你修改了值但前臺還沒有修改,可以加上這句:

控制項名.UpdateLayout();

之後在使用可視化樹,這一條的說法和形容可能有點不嚴謹,歡迎指正交流。

2.可視化樹使用的是遞歸的方法,所以它的效率不是很高,如果在程式中大量使用可視化樹,會使得程式變慢的。

3.調用可視化樹返回的列表如果沒有找到相應的控制項或是異常便會返回空值,所以建議在你遍歷可視化樹返回的列表時,請先判斷否非為空。

 

以上內容歡迎指正交流,還是小白。

2018.8.15下午五點半多兩分


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 List集合操作去除重覆數據的這種情況經常會碰到,博客園裡面也有很多大神們做過,在這裡主要是借鑒然後自己整理了一下,主要是為了方便自己,以後再次碰到這種去重問題,直接打開自己的鏈接拿起鍵盤就是乾,,,, 一、方法一 利用HashSet去重,在實體類里重寫Equals和GetHashCode方法 ...
  • 前言 前面講解了MEF的引用方法,介面的導入導出,類屬性的導入導出和集合的導出用法其實大家可以看到基本上大同小異的。 MEF的延遲載入 我們知道當裝配一個組件的時候,當前組件裡面的所有的Import的變數都自動去找到對應的Export而執行了實例化,有些時候出於程式效率的考慮,不需要立即實例化對象, ...
  • MEF導出類的方法和屬性 首先來說導出屬性,因為這個比較簡單,和導出類差不多,先來看看代碼,主要看我加註釋的地方,MusicBook.cs中的代碼如下: program.cs中的代碼如下: 下麵還用foreach遍歷輸出屬性的值,運行即可查看到結果。最後我會附上源碼供大家下載,這裡就不再截圖了。 下 ...
  • C 5.0 推出async和await,最早是.NET Framework 4.5引入,可以在Visual Studio 2012使用。在此之前的非同步編程實現難度較高,async使非同步編程的實現變得簡便。 各平臺對async的支持情況 |平臺|async| | | | |.NET 4.5及以上|& ...
  • 代碼: private static ImageCodecInfo GetImageCodecInfo(ImageFormat imageFormat) { ImageCodecInfo[] imageCodecInfoArr = ImageCodecInfo.GetImageDecoders(); ...
  • 前言 小編菜鳥級別的程式員最近感慨頗多,經歷了三五春秋深知程式路途遙遠而我滄海一粟看不到的盡頭到不了的終點何處是我停留的驛站。說了段廢話下麵進入正題吧! 什麼是MEF? MEF:全稱Managed Extensibility Framework(托管可擴展框架)。單從名字我們不難發現MEF是專門致力 ...
  • IoC理論的背景 我們都知道,在採用面向對象方法設計的軟體系統中,它的底層實現都是由N個對象組成的,所有的對象通過彼此的合作,最終實現系統的業務邏輯。 如果我們打開機械式手錶的後蓋,就會看到與上面類似的情形,各個齒輪分別帶動時針、分針和秒針順時針旋轉,從而在表盤上產生正確的時間。圖1中描述的就是這樣 ...
  • dotNet core 應用部署至 centos(超詳解附截圖) ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...