如何获取子控件 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>
默认情况下,ContentControl
s "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 内容控件将保持不变。唯一改变的是数据上下文。
在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>
默认情况下,ContentControl
s "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 内容控件将保持不变。唯一改变的是数据上下文。