近日需要在两个有继承关系的UserControl上实现类似的style,要命的是这style里还带有事件处理的c#代码。定义重复的style和c#代码是不可接受的。第一个想法是把相同的style和c#代码放在基类Control的xaml和class里,但是由于子类也要有自己的特定的xaml,visualStudio提示xaml里对应的class的基类不能是一个已经用xaml定义过的类。这一点要求太没有道理了,xaml就不能基类+子类混合一下吗?
没办法,只能让这两个有继承关系的Control都继承自一个没有定义过xaml的更上层的Control,然后他们两者自己有各自的xaml,但是,难道一些公共style不能用一个文件里的吗?当然可以,用这样的xaml就可以不但把style的xaml,也把style的c# code都包含进来了。
<local:ConfiguredDataGrid.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Resources/FilterStyle.xaml" />
如果用c#来写,就是类似
_resources = Application.LoadComponent(
new Uri(
"/xxxx.ClientUI;component/Resources/generic.xaml",
UriKind.Relative)) as ResourceDictionary;
这样的写法。
这其中的FilterStyle和generic两个xaml,可以仅仅是xaml文件,里面含有若干带有x:key的template,style,供包含了这个ResourceDictionary的xaml使用。但我需要带自己的c#事件处理代码,则必须有code behind的class,于是我令FilterStyle的root element就用了ResourceDictionary,而且这个ResourceDictionary带有x:Class
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="xxxx.Resources.FilterStyle"
于是.cs里就是一个ResourceDictionary的partial子类,可以用VisualStudio生成UserControl的模版来改。只是由于这不是一个真的UserControl,也就不能调用基类的InitializeComponent(),没有IDE帮忙生成的放在obj目录里的.g.cs文件,也不需要该helper class来声明xaml里标记的components。
public partial class FilterStyle : ResourceDictionary
{
public FilterStyle()
{
// InitializeComponent();
}
这样如果要在c#的事件处理逻辑里和xaml定义的components互动,就只能通过event handler的sender来遍历视觉树找到自己需要的东西了。
为何InitializeComponent()的定义在对应的.g.cs文件中?我忘记了
我知道了。是因为从工具箱中拖进组件中,就会自动生成这个方法。不打扰了!