首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WPF 控制模板進階:如何在後台修改 ControlTemplate 內部元素

     編輯:關於.NET

問題背景

直接設定 Button.Background 為 ImageBrush 時,滑鼠懸停會觸發預設樣式覆蓋背景,導致圖片消失。解法是建立自訂 ControlTemplate 將圖片作為內容呈現,但隨之而來的新挑戰是:如何在後台程式碼中動態修改模板內部的元素 (如更換圖片來源)?

解決方案:FindName 穿透命名邊界

ControlTemplate 有獨立的命名範圍。需先取得模板實例,再呼叫 FindName 並指定 FrameworkElement 作為命名範圍擁有者 (通常是套用模板的控件本身)。

步驟

  1. 在 XAML 為 ControlTemplate 指定 x:Name (或 x:Key 放入 Resources)
  2. 後台呼叫 button.Template.FindName("internalElementName", button)
  3. 轉型為目標類型並修改屬性

範例:按鈕模板內含 Image,後台切換圖片

<Button Name="btnSure" Click="btnSure_Click" Margin="10">
    <Button.Template>
        <ControlTemplate x:Name="ctSure">
            <ContentControl>
                <Image x:Name="imgWork" Source="/Oland.HSS.InHospital;component/Pictures/maintenance/1.png"/>
            </ContentControl>
        </ControlTemplate>
    </Button.Template>
</Button>

後台程式碼

private void Window_Loaded(object sender, RoutedEventArgs e) {
    if (!IsInMaintenance) {
        // 方式一:透過控件的 Template 屬性直接取得
        ControlTemplate template = btnSure.Template; // 若 Template 為直接指定
        // 方式二:若模板放在 Resources,用 TryFindResource
        // ControlTemplate template = (ControlTemplate)this.TryFindResource("TemplateKey");

        if (template != null) {
            // 關鍵:第二個參數必須傳入套用模板的控件 (btnSure) 作為命名範圍擁有者
            Image img = template.FindName("imgWork", btnSure) as Image;
            if (img != null) {
                img.Source = new BitmapImage(new Uri(@"../Pictures/maintenance/3.png", UriKind.Relative));
            }
        }
    }
}

常見陷阱與注意事項

  • 命名範圍隔離:ControlTemplate、DataTemplate、Style 皆建立獨立命名範圍,FindName 必須指定正確的範圍擁有者。
  • 模板尚未套用:在 Loaded 事件前模板可能尚未建立視覺樹,呼叫 FindName 會回傳 null。確保在 Loaded 或之後執行。
  • Template 為共享資源:若多個控件共用同一 ControlTemplate (來自 Resources),FindName 會返回「最後套用該模板的控件」對應的元素,需謹慎使用。建議每個需動態修改的控件使用獨立模板實例 (直接寫在 Button.Template 內)。

延伸討論:觸發器在觸控裝置的雙擊問題

文中提到加入 Trigger Property="Button.IsPressed" 縮放動畫後,觸控螢幕需點擊兩次才觸發 Click。可能原因:

  • RenderTransform 縮放導致觸點座標偏移,導致第二次觸控落在視覺樹外。
  • 觸控事件與滑鼠事件提升機制衝突。
  • 建議改用 LayoutTransform 或縮小縮放比例,或在 TouchDown/TouchUp 手動處理。

總結

修改 ControlTemplate 內部元素的關鍵在於 正確取得命名範圍擁有者並呼叫 FindName。掌握此技巧,即可在保持自訂視覺外觀的同時,保有後台動態調整 UI 的彈性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved