我正在研究创建类型安全的泛型控件。这是针对WPF 4和未来Silverlight中的(减少)泛型支持,并将包括一个泛型控件的层次结构。
我有两个问题:
ComponentResourceKey,因此下面描述的设置无法工作)。下面的测试泛型控件定义了两个测试属性:一个非泛型Description属性和一个泛型Data属性。该控件将DefaultStyleKey设置为控件的ComponentResourceKey。
下面是如何定义测试控件:
public class GenericControl<T> : Control {
static GenericControl( ) {
DefaultStyleKeyProperty.OverrideMetadata(
typeof(GenericControl<T>), new FrameworkPropertyMetadata(
new ComponentResourceKey( typeof(Proxy), "GenericControl`1" )
)
);
}
public static readonly DependencyProperty DescriptionProperty =
DependencyProperty.Register(
"Description", typeof(string), typeof(GenericControl<T>),
new PropertyMetadata( "Default Description" )
);
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register(
"Data", typeof(T), typeof(GenericControl<T>),
new PropertyMetadata( default(T) )
);
public string Description { get { ... } set { ... } }
public T Data { get { ... } set { ... } }
}下面是generic.xaml中测试控件的样式
<Style x:Key="{ComponentResourceKey {x:Type local:Proxy}, GenericControl`1}">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Control}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Description,
RelativeSource={RelativeSource TemplatedParent}}" />
<TextBlock Text="{Binding Data,
RelativeSource={RelativeSource TemplatedParent}}" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>以下是在xaml中如何声明此测试控件的一些示例:
<ListBox Name="list" ... />
<GenericControl x:TypeArguments="sys:Int32" Description="Count: "
Data="{Binding Items.Count, ElementName=list}" />
<Slider Name="slider" ... />
<GenericControl x:TypeArguments="sys:Double" Description="Slider Value: "
Data="{Binding Value, ElementName=slider}" />使用WPF 4中当前的泛型支持,您不能使用开放的泛型类型作为样式或控件模板的TargetType (这样做会产生“GenericControl1' TargetType does not match type of element 'GenericControl1”。例外情况)。如上文问题1所述,这有两个主要后果:
RelativeSource={RelativeSource TemplatedParent}的正常绑定,而不是控件模板中的TemplateBinding。Description属性创建样式设置器,即使它不依赖于控件的泛型类型。对于后者,WPF有一个解决办法:只需将非泛型属性定义为代理类型上附加的依赖项属性。然后可以使用AddOwner“声明”泛型控件上的属性,也可以在样式设置器中使用"ProxyType.Property“语法。当然,Silverlight不支持AddOwner,在任何情况下,将本应是实例属性的内容转换为附加属性并不理想,因此这并不是一个长期的解决方案。
旁白:看起来在类型的xaml解析行为中存在一个回归。使用VS2008,我可以使用{x:Type local:GenericControl`1}获取控件的开放类型,这是我在ComponentResourceKey中使用的示例类型。但是,在VS2010中,这会导致以下错误:“字符'' was unexpected in string 'local:GenericControl1'.无效的XAML类型名称”,因此我将其改为使用代理类型。
发布于 2010-04-12 13:56:57
我在WPF和银光论坛上发布了同样的问题。Silverlight没有收到任何答复,但以下是WPF的答复摘要:
TargetType="{x:Type local:GenericControl(x:Int32)}" )将适用于单个样式,但需要复制和粘贴才能针对其他类型参数的相同控件。XamlReader和一些字符串替换为任何给定类型参数动态创建默认模板,但在控件之外创建新样式或模板时仍有一些不理想之处。发布于 2009-12-19 06:46:20
SliderInt32 -> BaseRange -> BaseSliderControl
我们只能在BaseSliderControl或SliderInt32上定义样式,而不能在BaseRange上定义样式。我们可以在BaseRange类中指定泛型属性和非泛型属性,它们在SliderInt32中运行良好。
GenericControl`1 `1 etc名称不是正确的完全限定名,因此它将永远无法工作。
https://stackoverflow.com/questions/1930960
复制相似问题