Furqan Safdar
Furqan Safdar

Reputation: 16698

How to make common template with dynamic binding in WPF

I have created different controls in WPF with their respective control templates in which styling is almost similar but binding is different, as given below removing extra clutter. I am looking for a way to make a common ControlTemplate with some way to make the binding dynamic.

ControlTemplate for MasterRuleLayout control

<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 for MasterEntityLayout control

<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>

Upvotes: 0

Views: 714

Answers (1)

Mark Feldman
Mark Feldman

Reputation: 16119

Bindings need dependency properties to form the "glue" between the properties in your template bindings and the properties in the view models that you're binding to. That means your options are 1) use TemplateBinding to bind via existing properties in the templated parent, 2) create a custom control with any additional properties that are missing, or 3) use attached properties:

<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}" />

And then you would create the attached property itself like so:

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
}

Upvotes: 1

Related Questions