如何获取子控件 WPF 的 Datacontext

How to get Datacontext of Child control WPF

在App.xaml

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

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

在XAML中:

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

在 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);
}

在后面的代码中

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

这里我试图获取两个子控件的数据上下文,但它在 dc_Child1 和 dc_Child2 中显示父数据上下文。 有没有办法得到这两个的datacontext?

问题是设置 ContentControl.Content 与设置 ContentControl.DataContext 不同。

考虑这段代码。以下是视图模型:

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

这是标记:

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

默认情况下,ContentControls "inherit" DataContext 来自他们的 parent(在这种特殊情况下,来自 grand-parent、Window) .

如果点击按钮,后面的代码为:

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

会将 True 写入输出 window,因为两个控件的数据上下文都是 ParentViewModel.

的实例

但是如果XAML会稍微修改成这样:

    <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 将写入 False,因为这会显式设置 DataContext 并破坏默认的 "inheritance" 策略。请注意,这个表达式:

DataContext="{Binding Child_A}"

仍然适用于 parent DataContext,而这个:

Content="{Binding}"

使用新的数据上下文,它由先前的表达式分配。

另请注意,此示例中的 content 内容控件将保持不变。唯一改变的是数据上下文。