WPF DataTemplate Binding

19,053

Solution 1

You are using the ContentTemplate property incorrectly. From the ContentControl.ContentTemplate Property page on MSDN:

Gets or sets the data template used to display the content of the ContentControl.

Therefore, when setting this property, you also need to set the Content property to some sort of data source:

<TabControl>
    <TabItem Header="TabItem">
        <Label Content="{Binding Path=myString}"/>
    </TabItem>
    <TabItem Header="TabItem" Content="{Binding Path=myString}">
        <TabItem.ContentTemplate>
            <DataTemplate>
                <Label Content="{Binding}" />
            </DataTemplate>
        </TabItem.ContentTemplate>
    </TabItem>
</TabControl>

Solution 2

<TabItem Content="{Binding myString}" Header="TabItem">
    <TabItem.ContentTemplate>
        <DataTemplate>
            <Label Content="{Binding}" />
        </DataTemplate>
    </TabItem.ContentTemplate>
</TabItem>

But just so you know, to bind a window on itself, is just not the way to go. I don't know if you did that just for the example, but if not try and create a proper viewModel to bind your window on ;)

Share:
19,053
ejones
Author by

ejones

Updated on June 04, 2022

Comments

  • ejones
    ejones almost 2 years

    I discovered when using a ContentTemplate/DataTemplate in a WPF TabControl my Bindings will not work anymore.

    I have set up a small example to illustrate:

    <Window x:Class="HAND.BindingExample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="BindingExample" Height="506" Width="656"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        >
    <Grid>
        <TabControl HorizontalAlignment="Left" Height="381"  VerticalAlignment="Top" Width="608">
            <TabItem Header="TabItem">
                <Label Content="{Binding Path=myString}"/>
            </TabItem>
            <TabItem Header="TabItem">
                <TabItem.ContentTemplate>
                    <DataTemplate>
                        <Label Content="{Binding Path=myString}"/>
                    </DataTemplate>
                </TabItem.ContentTemplate>
            </TabItem>
        </TabControl>
    </Grid>
    </Window>
    

    Tab1 works as expected, Tab2 is empty.

    the code behind:

    using System.Windows;
    
    namespace HAND
    {
        public partial class BindingExample : Window
        {
            public string myString { get; set; }
    
            public BindingExample()
            {
                myString = "Hello Stackoverflow";
    
                InitializeComponent();
            }
        }
    }
    
  • Miiite
    Miiite almost 10 years
    I have it running on my machine. Maybe it does not run when you bind a window on itself, which I did not do.
  • ejones
    ejones almost 10 years
    Thank you! This works for my example. I am using a different binding class in my real world program using the MVVM pattern. I still do not understand why your code works and mine doesn't. I will now try to apply the solution of the example to my application.
  • Miiite
    Miiite almost 10 years
    Sheridan posted an answer with the same XAML code as mine, but with a better explanation of how the ContentTemplate works. It should help you understanding it
  • ejones
    ejones almost 10 years
    Yes, Thank you both of you!
  • ejones
    ejones almost 10 years
    Same conclusion as Miiite. Thank you very much also for the good explanation!
  • Sivasubramanian
    Sivasubramanian almost 10 years
    hi miiite, your answer worked for me, wrongly tested. make an edit to ur answer i will revert the downvote
  • stuzor
    stuzor almost 5 years
    why do you need to set the Content="{Binding Path=mystring}" in the <TabItem> AND then also set Content="{Binding}" in the <Label>? In this example it doesn't seem necessary for the TabItem.ContentTemplate at all? Wouldn't it work just as well without the Template? I'm trying to understand templates and how I can bind other properties of the Label to parent's DataContext... thanks!
  • Sheridan
    Sheridan almost 5 years
    We data bind the myString property to the Content property to give it some value. Here, that value is just a single string, but it could have been an object with other properties. In the ContentTemplate, we tell it which part of the data bound object we want to display in the Label. In this case, we want to bind to the whole string object, so we use {Binding} to do that.
  • wondra
    wondra almost 4 years
    Noto though: the sample would work only for read-only bindings - if you changed Label to TextBox, myString would never get written back.