是否可以在WPF中为通用基本控件提供默认样式?
假设我有以下基类:
public abstract class View<T> : ContentControl
where T : ViewModel
{
static View()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(View<T>),
new FrameworkPropertyMetadata(typeof(View<T>)));
}
// Other properties, methods, etc in here
}
public abstract class ViewModel
{
// Other properties, methods, etc in here
}
Run Code Online (Sandbox Code Playgroud)
假设我有两个继承自这些基类的类:
public partial class TestView : View<TestViewModel>
{
public TestView()
{
InitializeComponent();
}
// TestView specific methods, properties, etc
}
public class TestViewModel : ViewModel
{ /* TestViewModel specific methods, properties, etc */ }
Run Code Online (Sandbox Code Playgroud)
现在我想为我的派生控件使用的基本控件提供一个默认样式:
<Style TargetType="{x:Type local:View`1}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:View`1}">
<Border Background="Magenta"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel>
<Button>Test</Button>
<ContentPresenter ContentSource="Content" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)
但是,当我使用我的TestView控件时,我没有应用模板标记(因此我可能在我的TestView控件的XAML中定义的任何内容都不在视觉/逻辑树中).
我基本上试图采用我的基本视图/ viewmodel类并应用一致的外观.这当然适用于非通用基本视图案例.但是,我需要在视图和视图模型之间进行类型安全连接,这样我就可以从视图中调用视图模型上的方法(我知道这些方法可能与某些人已经实现MVVM的方式"坐得不好").
我发现涉及定制的相当简单的解决方案TypeExtension.
1 - 将DefaultStyleKey设置为CodeNaked的答案中提到的默认泛型类型:
DefaultStyleKeyProperty.OverrideMetadata(typeof(View<T>),
new FrameworkPropertyMetadata(typeof(View<>)));Run Code Online (Sandbox Code Playgroud)
2 - 创建以下类而不是继承自 System.Windows.Markup.TypeExtension
[System.Windows.Markup.ContentProperty("Type")]
public class TypeExtension : System.Windows.Markup.TypeExtension
{
public TypeExtension()
: base()
{ }
public TypeExtension(Type type)
: base(type)
{ }
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (Type == null)
throw new InvalidOperationException("Must specify the Type");
return Type;
}
}
Run Code Online (Sandbox Code Playgroud)
3 - 更新样式的TargetType以指向新local:Type扩展名而不是通常的x:Type扩展名
<Style>
<Style.TargetType>
<local:Type Type="{x:Type local:View`1}" />
</Style.TargetType>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Control}">
. . .
Run Code Online (Sandbox Code Playgroud)
多数民众赞成.但有一点需要注意,当您尝试绑定/设置View <T>类中定义的任何依赖项属性时,VS会抛出编译错误.所以你不能使用像{TemplateBinding ViewTProperty}... 这样的简单语法
| 归档时间: |
|
| 查看次数: |
2659 次 |
| 最近记录: |