如何在 WPF 中使用动态绑定制作通用模板
How to make common template with dynamic binding in WPF
我在 WPF 中使用各自的控件模板创建了不同的控件,其中样式几乎相似但绑定不同,如下所示,消除了多余的混乱。我正在寻找一种方法来创建一个通用 ControlTemplate
以及一些使绑定动态化的方法。
ControlTemplate
MasterRuleLayout 控件
<ControlTemplate TargetType="{x:Type local:MasterRuleLayout}">
<StackPanel>
<Image
Style="{StaticResource MasterLayoutImageStyle}"
DataContext="{Binding CommonAggregate.SelectedRule}">
</Image>
<TextBox
Text="{Binding CommonAggregate.SelectedRule.Name}">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding CommonAggregate.SelectedRule.Parent}"
Value="{x:Null}">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</StackPanel>
</ControlTemplate>
ControlTemplate
MasterEntityLayout 控件
<ControlTemplate TargetType="{x:Type local:MasterEntityLayout}">
<StackPanel>
<Image
Style="{StaticResource MasterLayoutImageStyle}"
DataContext="{Binding CommonAggregate.SelectedEntityItem}">
</Image>
<TextBox
Text="{Binding CommonAggregate.SelectedEntityItem.Name}">
</TextBox>
</StackPanel>
</ControlTemplate>
绑定需要依赖属性来形成模板绑定中的属性和要绑定到的视图模型中的属性之间的 "glue"。这意味着您的选择是 1) 使用 TemplateBinding 通过模板化父级中的现有属性进行绑定,2) 使用缺少的任何其他属性创建自定义控件,或 3) 使用附加属性:
<Window.Resources>
<ControlTemplate x:Key="MyTemplate" TargetType="{x:Type Control}">
<TextBlock Text="{Binding Path=(local:AttachedProps.Name), Mode=OneWay,
RelativeSource={RelativeSource TemplatedParent}}" />
</ControlTemplate>
</Window.Resources>
<Control Template="{StaticResource MyTemplate}"
local:AttachedProps.Name="{Binding MyViewModelName, Mode=OneWay}" />
然后您将像这样创建附加的 属性 本身:
public static class AttachedProps
{
#region Name
public static string GetName(DependencyObject obj)
{
return (string)obj.GetValue(NameProperty);
}
public static void SetName(DependencyObject obj, string value)
{
obj.SetValue(NameProperty, value);
}
public static readonly DependencyProperty NameProperty =
DependencyProperty.RegisterAttached("Name", typeof(string),
typeof(AttachedProps), new PropertyMetadata(String.Empty));
#endregion Name
}
我在 WPF 中使用各自的控件模板创建了不同的控件,其中样式几乎相似但绑定不同,如下所示,消除了多余的混乱。我正在寻找一种方法来创建一个通用 ControlTemplate
以及一些使绑定动态化的方法。
ControlTemplate
MasterRuleLayout 控件
<ControlTemplate TargetType="{x:Type local:MasterRuleLayout}">
<StackPanel>
<Image
Style="{StaticResource MasterLayoutImageStyle}"
DataContext="{Binding CommonAggregate.SelectedRule}">
</Image>
<TextBox
Text="{Binding CommonAggregate.SelectedRule.Name}">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding CommonAggregate.SelectedRule.Parent}"
Value="{x:Null}">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</StackPanel>
</ControlTemplate>
ControlTemplate
MasterEntityLayout 控件
<ControlTemplate TargetType="{x:Type local:MasterEntityLayout}">
<StackPanel>
<Image
Style="{StaticResource MasterLayoutImageStyle}"
DataContext="{Binding CommonAggregate.SelectedEntityItem}">
</Image>
<TextBox
Text="{Binding CommonAggregate.SelectedEntityItem.Name}">
</TextBox>
</StackPanel>
</ControlTemplate>
绑定需要依赖属性来形成模板绑定中的属性和要绑定到的视图模型中的属性之间的 "glue"。这意味着您的选择是 1) 使用 TemplateBinding 通过模板化父级中的现有属性进行绑定,2) 使用缺少的任何其他属性创建自定义控件,或 3) 使用附加属性:
<Window.Resources>
<ControlTemplate x:Key="MyTemplate" TargetType="{x:Type Control}">
<TextBlock Text="{Binding Path=(local:AttachedProps.Name), Mode=OneWay,
RelativeSource={RelativeSource TemplatedParent}}" />
</ControlTemplate>
</Window.Resources>
<Control Template="{StaticResource MyTemplate}"
local:AttachedProps.Name="{Binding MyViewModelName, Mode=OneWay}" />
然后您将像这样创建附加的 属性 本身:
public static class AttachedProps
{
#region Name
public static string GetName(DependencyObject obj)
{
return (string)obj.GetValue(NameProperty);
}
public static void SetName(DependencyObject obj, string value)
{
obj.SetValue(NameProperty, value);
}
public static readonly DependencyProperty NameProperty =
DependencyProperty.RegisterAttached("Name", typeof(string),
typeof(AttachedProps), new PropertyMetadata(String.Empty));
#endregion Name
}