Home > Software engineering >  Binding elements into a DataTemplate in WPF Window
Binding elements into a DataTemplate in WPF Window

Time:04-29

I have five definitions of DataTemplate in my window, according with a CantidadLlantas property, I choose one of these to show it. Until here all works fine.

But, in each DataTemplate there are some TextBox with Text property binding to one property in my ViewModel, and this isn't working, if I show these same properties in TextBoxes out of the DataTemplates the values shown are ok, is like if the binding not is binding into the DataTemplates... Why?

One of the templates the more simple is the next:

<Window.Resources>
<DataTemplate x:Name="Llantas2Template" x:Key="Llantas2Template"  DataType="ContentControl">
    <Grid Name="grdLlantas">
        <Border Name="borLlantas" BorderBrush="Black" BorderThickness="1" Margin="0,0,0,0" Background="DarkSeaGreen" />
        <Rectangle Fill="Yellow" HorizontalAlignment="Left" Height="30" Stroke="Black" VerticalAlignment="Top" Width="5" Margin="0,16,0,0" />
        <Rectangle Fill="Yellow" HorizontalAlignment="Left" Height="30" Stroke="Black" VerticalAlignment="Top" Width="5" Margin="0,130,0,0" />
        <Rectangle HorizontalAlignment="Left" Height="175" Stroke="Black" StrokeThickness="3" VerticalAlignment="Top" Width="70" Margin="20,10,10,10" />
        <Line X1="230" Y1="10" X2="230" Y2="150" Stroke="Black" StrokeThickness="3" />
        <Ellipse Fill="Black" Height="25" Width="10" StrokeThickness="2" Stroke="Black" Margin="180,0,0,10"/>

        <TextBox Name="txtLlanta2" Margin="200,10,20,20" ToolTipService.ToolTip="Llanta trasera derecha" 
                        Width="60" Height="25" HorizontalAlignment="Left" VerticalAlignment="Top" 
                        Text="{Binding Llanta2,  Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Name="txtLlanta1" Margin="200,150,20,10" ToolTipService.ToolTip="Llanta trasera izquierda" 
                        Width="60" Height="25" HorizontalAlignment="Left" VerticalAlignment="Top" 
                        Text="{Binding Llanta1,  Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    </Grid>
</DataTemplate>

Then in the window I declare a ContentControl into a StackPanel the visibility of which depends of a property in my ViewModel, this works fine:

<StackPanel Name="stkLlantas" Grid.Row="2"  Visibility="{Binding IsVisibilityTemplate}" >
    <!--Aquí se pondrá el UserControl con el Template de Llantas que corresponde-->
<ContentControl Grid.Row="2" Name="LlantasContent" 
                    VerticalAlignment="Stretch" HorizontalAlignment="Center" 
                    Margin="0,10,0,10" />            
</StackPanel>

the selection of the template is in behind:

#region DefineTemplate
private void DefineTemplate()
{
     switch (cantidadLlantas)
     {
         case 2:
             LlantasContent.ContentTemplate = (DataTemplate)this.FindResource("Llantas2Template");
             break;
         case 4:
             LlantasContent.ContentTemplate = (DataTemplate)this.FindResource("Llantas4Template");
             break;
         case 6:
             LlantasContent.ContentTemplate = (DataTemplate)this.FindResource("Llantas6Template");
             break;
         case 8:
             LlantasContent.ContentTemplate = (DataTemplate)this.FindResource("Llantas8Template");
             break;
         case 10:
             LlantasContent.ContentTemplate = (DataTemplate)this.FindResource("Llantas10Template");
             break;
         default:
             LlantasContent.ContentTemplate = null;
             break;
     }
 }
 #endregion

In behind I define the DataContext for my window:

    UnidadLlantasVM viewModel;

    int cantidadLlantas;
    public wUnidadLlantas(string _IDUni, int _CantidadLlantas)
    {
        this.Loaded  = (s, a) =>
        {
            cantidadLlantas = _CantidadLlantas;

            viewModel = new UnidadLlantasVM();

            viewModel.IDUni = _IDUni;
            viewModel.CantidadLlantas = _CantidadLlantas;

            this.DataContext = viewModel;

            DefineTemplate();
        }; 

        InitializeComponent();

    }

And in xaml:

    <Window x:Class="MTTO.wUnidadLlantas"   
                DataContext="{Binding RelativeSource={RelativeSource Self}}" 

With test purposes, I add TextBoxes in the window, with the same properties that should be showed into the template and here works fine, anex the image:

enter image description here

all the data sowed in the window are properties of my ViewModel and works fine, but into the template not, the TextBoxes in the picture down should be the same that the TextBoxes pointed in red. What happen? I have a Silverlight project with the same, and there works fine...

CodePudding user response:

Probably you need to bind the DataContext to the ContentControl's Content property (which to me has a little smell of a design flaw in WPF, but never mind).

<StackPanel Name="stkLlantas" Grid.Row="2"  Visibility="{Binding IsVisibilityTemplate}" >
    <!--Aquí se pondrá el UserControl con el Template de Llantas que corresponde-->
<ContentControl Grid.Row="2" Name="LlantasContent" 
                    Content="{Binding}"
                    VerticalAlignment="Stretch" HorizontalAlignment="Center" 
                    Margin="0,10,0,10" />            
</StackPanel

By the way, consider using a ContentTemplateSelector, for the thing you do in DefineTemplate. This is the default API for template selection. You would move your existing code and logic from Define Template to SelectTemplate.

https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.contentcontrol.contenttemplateselector?view=windowsdesktop-6.0 https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.datatemplateselector.selecttemplate?view=windowsdesktop-6.0

  • Related