Dark Knight
Dark Knight

Reputation: 3577

How to get Datacontext of Child control WPF

In App.xaml

<DataTemplate DataType="{x:Type vm:CurrentSheetVM}">
                    <vw:CurrentSheetV/>
                </DataTemplate>

    <DataTemplate DataType="{x:Type vm:ParentVM}">
                    <vw:ParentControlV/>
                </DataTemplate>

In XAML:

 <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" > 
                <ContentControl Name="childCtrl1" Content="{Binding CurrentSheet1}"/>
                <ContentControl Name="childCtrl2" Content="{Binding CurrentSheet2}"/>
    </StackPanel>

In ParentVM:

private ViewModelBase currentSheet1;
       public ViewModelBase CurrentSheet1
       {
           get { return currentSheet1; }
           set { currentSheet = value;
           this.OnPropertyChanged("CurrentSheet1");
           }
       }

public ParentVM()
{
CurrentSheet1= new CurrentSheetVM(some param1);
CurrentSheet2= new CurrentSheetVM(some param2);
}

in code behind

Object dc_Child1= childCtrl1.DataContext;
Object dc_Child2= childCtrl2.DataContext;

Here am trying to get the datacontext of both child controls,but its showing parents DataContext in dc_Child1 and dc_Child2. Is there a way to get the datacontexts of these two?

Upvotes: 2

Views: 3939

Answers (1)

Dennis
Dennis

Reputation: 37770

The problem is that setting ContentControl.Content is not the same, as setting ContentControl.DataContext.

Consider this code. Here are view models:

public class ParentViewModel
{
    public ChildViewModel_A Child_A { get; } = new ChildViewModel_A
    {
        IntProperty = 100
    };

    public ChildViewModel_B Child_B { get; } = new ChildViewModel_B
    {
        StringProperty = "Hello, world!"
    };
}

public class ChildViewModel_A
{
    public int IntProperty { get; set; }
}

public class ChildViewModel_B
{
    public string StringProperty { get; set; }
}

Here is markup:

<Window x:Class="DataContextsDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DataContextsDemo">

    <Window.DataContext>
        <local:ParentViewModel />
    </Window.DataContext>

    <StackPanel>
        <StackPanel.Resources>
            <DataTemplate DataType="{x:Type local:ChildViewModel_A}">
                <TextBlock Text="{Binding IntProperty}"/>
            </DataTemplate>
            <DataTemplate DataType="{x:Type local:ChildViewModel_B}">
                <TextBlock Text="{Binding StringProperty}"/>
            </DataTemplate>
        </StackPanel.Resources>

        <ContentControl x:Name="Child_A_View" Content="{Binding Child_A}"/>
        <ContentControl x:Name="Child_B_View" Content="{Binding Child_B}"/>
        <Button Content="Click me!" Click="Button_Click"/>
    </StackPanel>
</Window>

By default both ContentControls "inherit" DataContext from their parent (in this particular case, from grand-parent, Window).

If you will click the button, this code in code behind:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Debug.WriteLine(Child_A_View.DataContext == Child_B_View.DataContext);
}

will write True into output window, because data context of both controls is instance of ParentViewModel.

But if XAML will be modified a little like this:

    <ContentControl x:Name="Child_A_View" DataContext="{Binding Child_A}" Content="{Binding}"/>
    <ContentControl x:Name="Child_B_View" DataContext="{Binding Child_B}" Content="{Binding}"/>

Debug.WriteLine will write False, because this sets DataContext explicitly and breaks default "inheritance" strategy. Note, that this expression:

DataContext="{Binding Child_A}"

still works with parent DataContext, while this one:

Content="{Binding}"

works with new data context, which is assigned by previous expression.

Also note, that content of content controls in this sample will remain the same. The only thing, that changes is a data context.

Upvotes: 3

Related Questions