要深入理解 WPF 設計時框架,除錯能力至關重要。透過以下設定即可對控件的設計時代碼進行除錯:
devenv.exe(Visual Studio IDE 的啟動程式)。完成這兩個步驟後,即可對設計時邏輯進行中斷點除錯,觀察設計器如何載入與呈現控件。
在設計介面選取控件時,該控件會成為可編輯的對象。設計環境回傳一個 ModelItem 類別,它封裝了對控件視圖的所有變更,支援互動操作。這與直接修改 WPF 控件屬性有所不同:
// 直接修改控件(僅影響視圖,不更新 XAML)
this.Content = "Hello";
在設計環境中,必須透過 ModelItem 來修改屬性,才能同步更新 XAML:
// 正確做法:透過 ModelItem.Properties 設定值
selectedContent.Properties["Content"].SetValue("Hello");
// 或使用靜態屬性識別碼
selectedContent.Properties[ContentControl.ContentProperty].SetValue("Hello");
ModelItem 透過 MenuActionEventArgs 傳遞。當需要交易支援時,使用 ModelEditingScope:
using (ModelEditingScope scope = selectedContent.BeginEdit("test")) {
selectedContent.Properties["Content"].SetValue("TextModelEditingScope");
selectedContent.Properties["Foreground"].SetValue(Brushes.Green);
scope.Complete(); // 全部成功才認可
}
若中途發生錯誤且未呼叫 Complete(),所有變更將回滾,確保資料一致性。
裝飾器對應 ASP.NET 中 GridView 右側的智慧標籤面板,提供視覺化操作介面。WPF 內建控件鮮少提供此功能,且無法擴充內建控件的設計時行為。
裝飾器由 AdornerProvider 提供,通常繼承 PrimarySelectionAdornerProvider 並覆寫 Activate 與 Deactivate 方法。
Activate 中):protected override void Activate(ModelItem item, DependencyObject view) {
Slider opacitySlider = new Slider { Background = Brushes.Red };
AdornerPanel myPanel = new AdornerPanel();
myPanel.Children.Add(opacitySlider);
Adorners.Add(myPanel);
base.Activate(item, view);
}
注意:Activate 也會傳入 ModelItem,意味著裝飾器也能修改控件視圖。
AdornerPlacementCollection 設定位置與大小,再透過 AdornerPanel.SetPlacements 套用。AdornerPlacementCollection 提供 8 個方法,實質上是 4 組寬/高相關的配對方法,參數皆為「倍數因子」與「偏移量」。以下以紅色 Slider 為例說明:
AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.SizeRelativeToContentWidth(1, 0); // 寬度 = 控件內容寬度 × 1
placement.SizeRelativeToContentHeight(1, 0); // 高度 = 控件內容高度 × 1
AdornerPanel.SetPlacements(opacitySlider, placement);
placement.PositionRelativeToAdornerWidth(1, 0); // 正數向右,負數向左
// 同時改變位置與寬度
placement.SizeRelativeToAdornerDesiredWidth(1, 0);
// 僅改變寬度(搭配 PositionRelativeToContentWidth)
placement.PositionRelativeToContentWidth(1, 0);
placement.SizeRelativeToAdornerDesiredWidth(5, 0);
AdornerPlacementCollection placement = new AdornerPlacementCollection();
placement.SizeRelativeToContentWidth(1, 0);
placement.PositionRelativeToAdornerWidth(1, 0);
placement.SizeRelativeToAdornerDesiredHeight(1, 0);
AdornerPanel.SetPlacements(opacitySlider, placement);
建議多嘗試不同組合,以掌握裝飾器定位的精髓。