gpt4 book ai didi

c# - 设置通用 WPF 控件的样式

转载 作者:行者123 更新时间:2023-11-30 16:35:18 24 4
gpt4 key购买 nike

我正在研究创建类型安全的通用控件。这是针对 (reduced) generics support在 WPF 4 和 future 的 Silverlight 中,并将包含通用控件的层次结构。

我有两个问题:

  1. 您能否对通用控件上定义的非通用属性使用样式 setter 和模板绑定(bind)?
  2. 在 Silverlight 中,是否有一个值可以用于基类中的默认样式键,从而允许在(临时)特定类型的派生类中使用相同的样式? (ComponentResourceKey 在 Silverlight 中不存在,因此下面描述的设置不起作用。)

下面的测试通用控件定义了两个测试属性:一个非通用的 Description 属性和一个通用的 Data 属性。控件集DefaultStyleKeyComponentResourceKey用于控制。

测试控制的定义如下:

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(这样做会导致“'GenericControl`1' TargetType does not匹配元素 'GenericControl`1' 的类型。”异常)。如上文问题 1 所述,这有两个主要后果:

  • 您必须在控件模板中使用 RelativeSource={RelativeSource TemplatedParent} 而不是 TemplateBinding 的普通绑定(bind)来引用通用控件定义的属性。
  • 您不能为 Description 属性创建样式 setter ,即使它不依赖于控件的通用类型也是如此。

对于后者,WPF 中有一个解决方法:只需将非泛型属性定义为代理类型的附加依赖属性。然后你可以使用AddOwner在通用控件上“声明”属性,您可以在样式 setter 中使用“ProxyType.Property”语法。当然,Silverlight 不支持 AddOwner,将应该是实例属性的东西变成附加属性在任何情况下都不是理想的,所以这不是一个真正的长期解决方案。

旁白:看起来类型的 xaml 解析行为出现了回归。使用 VS2008,我可以使用 {x:Type local:GenericControl`1} 获取控件的开放类型,我在 ComponentResourceKey 中将其用作示例类型。但是在 VS2010 中,这会导致以下错误:“字符 '`' 在字符串 'local:GenericControl'1' 中是意外的。无效的 XAML 类型名称。”,因此我将其改为使用代理类型。

最佳答案

我将同样的问题发布到 WPFSilverlight论坛。 Silverlight 上没有响应,但这里是 WPF 的答案摘要:

  • 引用Shreedhar , "XAML 当前不支持指定开放泛型类型"。
  • 使用封闭的通用类型,例如 TargetType="{x:Type local:GenericControl(x:Int32)}",将适用于单独的样式,但需要复制和-粘贴以针对其他类型参数的相同控件。
  • 可以使用 XamlReader 和一些字符串替换为任何给定的类型参数即时创建默认模板,但这在控件外部创建新样式或模板时仍有一些不足之处。<

关于c# - 设置通用 WPF 控件的样式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1930960/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com