WPF 設計器允許定義集合屬性可接受的項目類型。以 DataGrid.Columns 為例,它包含多種欄位類型(DataGridTextColumn、DataGridCheckBoxColumn 等)。要在設計器中顯示這些類型,需套用 NewItemTypesAttribute 中繼資料:
NewItemTypesAttribute attr = new NewItemTypesAttribute(
typeof(DataGridTextColumn),
typeof(DataGridCheckBoxColumn),
typeof(DataGridHyperlinkColumn),
typeof(DataGridComboBoxColumn),
typeof(DataGridTemplateColumn));
builder.AddCustomAttributes("Columns", attr);
此中繼資料可透過 AttributeTableBuilder 加入,或直接標註在屬性上,兩者效果相同。
每個類型在設計器下拉選單中需顯示不同圖示與名稱,這由 NewItemFactory 抽象類別負責,需覆寫三個虛擬方法:
CreateInstance:建立實例時執行業務邏輯(如設定預設 Header)GetDisplayName:回傳顯示名稱GetImage:回傳圖示internal class DataGridColumnFactory : NewItemFactory {
public override object CreateInstance(Type type) {
DataGridColumn col = null;
if (type.IsAssignableFrom(typeof(DataGridTemplateColumn))) {
col = CreateTemplateColumn();
} else {
col = Activator.CreateInstance(type) as DataGridColumn;
}
if (col != null) col.Header = "Header";
return col;
}
private static DataGridTemplateColumn CreateTemplateColumn() {
var col = new DataGridTemplateColumn();
col.CellTemplate = new DataTemplate();
col.CellEditingTemplate = new DataTemplate();
return col;
}
public override object GetImage(Type type, Size desiredSize) {
if (typeof(DataGridTextColumn).IsAssignableFrom(type))
return Util.GetImage("DataGridTextColumn.png", desiredSize);
// ... 其他類型對應圖示
return base.GetImage(type, desiredSize);
}
}
定義完成後,指定 FactoryType:
attr.FactoryType = typeof(DataGridColumnFactory);
選取 DataGrid 時右鍵會出現自訂選單(如「產生欄位」、「新增/編輯欄位...」),此功能透過繼承 PrimarySelectionContextMenuProvider 實現。
MenuGroup(選單群組)與 MenuAction(選單項目)。MenuGroup.Items 加入 MenuAction。UpdateItemStatus 事件動態啟用/停用選單項目。MenuAction.Execute 事件處理點擊邏輯。public DataGridMenuProvider() {
MenuGroup dataGroup = new MenuGroup("DataGroup", "DataGrid");
// 建立各 MenuAction 並掛接 Execute 事件
generateStockColumnsMenuAction.Execute += GenerateStockColumnsMenuAction_Execute;
// ...
dataGroup.HasDropDown = true;
dataGroup.Items.Add(isDatasourceSetMenuAction);
dataGroup.Items.Add(generateStockColumnsMenuAction);
// ...
this.Items.Add(dataGroup);
UpdateItemStatus += DataGridMenuProvider_UpdateItemStatus;
}
MenuAction.Execute 事件可觸發設計時與執行時控件的互動,涉及編輯模型(ModelItem)操作,將在下一篇詳細說明。