如何在 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
}