WPF- Binding properties in a DataTemplate

2.2k Views Asked by At

I'm building a window with a set of rows that share the same layout, but their contents should be different, eg:

| (Label Content:)"Name1" | (Textbox Text)"SomeText"  |
| (Label Content:)"Name5" | (Textbox Text)"OtherText" |

I've defined a DataTemplate which basically holds a Grid specifying the size of each column, holds all the elements it requires (a few labels, textboxes, etc.) and sets their common properties.

<UserControl.Resources>
    <DataTemplate x:Key="AxisRangeEntry" x:Shared="False">
            <Grid HorizontalAlignment="Stretch" VerticalAlignment="Top">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="50" />
                    <ColumnDefinition Width="50" />
                    ....
                </Grid.ColumnDefinitions>
                <Label x:Name="MyLabel" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Center">
                ...
                <TextBox x:Name="MyTextbox" Grid.Column="2" Width="110" HorizontalContentAlignment="Right" />
                ...
           </Grid>
    </DataTemplate>
</UserControl.Resources>

Then in my window I start adding the data template as ContentControls in a stack panel:

<ContentControl ContentTemplate="{StaticResource AxisRangeEntry}" />
<ContentControl ContentTemplate="{StaticResource AxisRangeEntry}" />
....

I'm struggling to figure out how I can define certain properties of controls inside the DataTemplate to be bindable to, and bind them to a static value/external property when I start defining the ContentControls. Effectively each ContentControl would need to be able to define things like it's MyLabel content and MyTextbox text.

I've previously created CustomControls, which had DependencyProperties on them, which I could then bind to when adding them on another window. With a DataTemplate however I'm not sure how I would define these fields as bindable and bind to them when including a new version of the template.

Any help would be appreciated.

2

There are 2 best solutions below

0
On

From what it sounds like, you are not using the MVVM pattern.

For your situation, I'd recommend using MVVM -- take a look at this article for a quick intro for something that would fit your case (ItemsControl with an ItemTemplate)

What you would do is create an ObservableObject to represent each row, and then bind the collection of ObservableObjects to an ItemsControl's ItemsSource, with the ItemTemplate set to the DataTemplate you created. In the DataTemplate, you would specify each binding to the property on the ObservableObject's row, and WPF would bind to the correct instance for each row.

http://www.wpf-tutorial.com/list-controls/itemscontrol/

Either way, DataTemplates are primarily used for templating a certain data-type. If you really need to implement the view in this way, a custom UserControl with dependency properties would be the way to go.

0
On

You present a dynamic nature of items to be bound, so this answer will attempt to provide guidance within the parameter's set.

...[to] define certain properties of controls inside the DataTemplate to be bindable to,

  1. Within a template the binding will default to the parents data context. Simply saying {Binding} will default to that item in the data context. If the bound item has a specific property then use {Binding MyPropertyName}. Just verify that the parent, or its ancestors have a valid data context.
  2. Think of data templates in its final location, as if you had hard coded it there. It will behave the same....

and bind them to a static value/external property when I start defining the ContentControls.

  1. Since this sounds like it is in a custom control, the datacontext will be the ultimate consumer's datacontext and most likely the datacontext will be worthless.
  2. If it is on a custom control, then use named binding and bind it to a property on the control. For example the control's name, in XAML, is given the name "MyControl" (x:Name="MyControl")and in the template binding, one can path directly to it such as

    {Binding MyCustomControlDependencyProperty, ElementName=MyControl}

created CustomControls, which had Dependency properties

With the above rules one can still, and should IMHO, use dependency properties of the custom control to pass on the information from the consumer to the the datatemplate which will use it dynamically..