本示例来自于wpf程序设计指南,部分代码稍做调整
本示例使用反射机制读取程序集中所有继承自Control的类包括本Control自身,并选择相应的菜单项后会在窗体中创建相应的控件。
并会自动升成Xaml文件
示例效果 图1
图2
图3
代码部分包括一个ControlMenuItem类型派生自MenuItem,该类型创建一个“包含所有Control子类型”的菜单。每个子菜单项的Header都显示出类型的名称,Tag 属性存储该类型的Type对象。
示例代码:
代码
public class ControlMenuItem : MenuItem
{
public ControlMenuItem()
{
var assembly = Assembly.GetAssembly(typeof(Control));
var aTypes = assembly.GetTypes();
var sortList = new SortedList<string, MenuItem>();
Header = "Control";
Tag = typeof(Control);
sortList.Add("Control", this);
foreach (var type in aTypes)
{
if (type.IsPublic &&
type.IsSubclassOf(typeof(Control)))
{
sortList.Add(type.Name,
new MenuItem
{
Header = type.Name,
Tag = type
});
}
}
foreach (var kvp in sortList)
{
if (kvp.Key == "Control") continue;
var strParent = ((Type)kvp.Value.Tag).BaseType.Name;
var itemParent = sortList[strParent];
itemParent.Items.Add(kvp.Value);
}
foreach (var kvp in sortList)
{
var type = (Type)kvp.Value.Tag;
if (type.IsAbstract && kvp.Value.Items.Count == 0)
kvp.Value.IsEnabled = false;
else
kvp.Value.Items.Insert(0,
new MenuItem
{
Header = kvp.Value.Header as string,
Tag = type
});
}
}
}
{
public ControlMenuItem()
{
var assembly = Assembly.GetAssembly(typeof(Control));
var aTypes = assembly.GetTypes();
var sortList = new SortedList<string, MenuItem>();
Header = "Control";
Tag = typeof(Control);
sortList.Add("Control", this);
foreach (var type in aTypes)
{
if (type.IsPublic &&
type.IsSubclassOf(typeof(Control)))
{
sortList.Add(type.Name,
new MenuItem
{
Header = type.Name,
Tag = type
});
}
}
foreach (var kvp in sortList)
{
if (kvp.Key == "Control") continue;
var strParent = ((Type)kvp.Value.Tag).BaseType.Name;
var itemParent = sortList[strParent];
itemParent.Items.Add(kvp.Value);
}
foreach (var kvp in sortList)
{
var type = (Type)kvp.Value.Tag;
if (type.IsAbstract && kvp.Value.Items.Count == 0)
kvp.Value.IsEnabled = false;
else
kvp.Value.Items.Insert(0,
new MenuItem
{
Header = kvp.Value.Header as string,
Tag = type
});
}
}
}
所有派生自ContentControl的类型都使用ContentPresenter类型的对象来显示它们的内容。ContentPresenter派生自FrameworkElement,你可以在模板的视觉树内包含一个ContentPresenter对象。比起“内容一定要是字符串”的假设,新的作法好多了。
Wpf定义的任何具有视觉外观的控件,都已经将期Template设定为ControlTemplate类型的对象,当你将Template Property设定成你自己的ControlTemplate时,你等于是将原来的模板取代掉。