是否可以在一个用户控件中有两个不同的数据上下文
本文关键字:两个 上下文 数据 用户 一个 控件 是否 | 更新日期: 2023-09-27 18:32:01
是否可以在一个用户控件中有两个不同的DataContext
?我想访问我的一个Model
对象,以及 MainViewModel 中的属性。例子:
类数据DataContext
(模型中定义的对象):
<DataGrid x:Name="PropertiesControl1" Height="auto" ItemsSource="{Binding ClassDatas}" HeadersVisibility="None" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="True">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Fields}" Header="" Width="*" IsReadOnly="True"/>
</DataGrid.Columns>
</DataGrid>
主视图模型DataContext
:
<TextBox x:Name="txtFields" Text="{Binding FieldsTextProperty, UpdateSourceTrigger=PropertyChanged}" Height="23" TextWrapping="NoWrap" Background="#FFCBEECD" AcceptsReturn="False" >.....</TextBox>
进一步,如何将它们结合起来?
<TextBox x:Name="txtFields" Text="{Binding FieldsTextProperty, UpdateSourceTrigger=PropertyChanged}" Height="23" TextWrapping="NoWrap" Background="#FFCBEECD" AcceptsReturn="False" >
<i:Interaction.Triggers>
<iex:KeyTrigger Key="Enter">
<cmd:EventToCommand Command="{Binding DataContext.AddFieldCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" PassEventArgsToCommand="True"/>
</iex:KeyTrigger>
</i:Interaction.Triggers>
</TextBox>
FieldsTextProperty
是来自MainViewModel
的DataContext
,EventToCommand
包含来自我的对象的DataContext
。
不,控件只能将单个对象设置为其DataContext
属性
但是,绑定不必绑定到它的DataContext
。可以使用其他绑定属性为绑定指定不同的源。用于更改绑定源的常用属性包括 Source
、RelativeSource
和 ElementName
。
-
可以仅更改特定绑定的绑定源,例如在
Command
绑定中所做的那样 -
或者,可以通过设置控件的
DataContext
属性或将控件的 属性绑定到其他内容来更改整个控件的它
实际上,我看到WPF初学者对DataContext
感到困惑,以至于我写了一篇关于它的博客文章。您可能有兴趣阅读它:您所说的"数据上下文"是什么?
这是我用来帮助演示DataContext
的代码块:
假设我们将一个窗口绑定到一个名为
ClassA
的对象。ClassA
有一个名为ClassB
的属性,ClassA
和ClassB
都有一个名为Name
的属性。下面是一个 XAML 块,它说明了 DataContext 的工作原理。它还包括一个示例,说明控件如何引用不在自己的 DataContext 中的属性。
public partial class MyWindow: Window
{
public MyWindow()
{
InitializeComponent();
this.DataContext = new ClassA();
}
}
public class ClassA
{
public string Name { get; set; }
public ClassB ClassB { get; set; }
}
public class ClassB
{
public string Name { get; set; }
}
<!-- DataContext set to ClassA in initialization code -->
<Window x:Name="MyWindow">
<!-- DataContext here is not specified, so it's inherited
from its parent's DataContext, which is ClassA -->
<StackPanel>
<!-- DataContext inherited from parent, which is
ClassA, so this will display ClassA.Name -->
<Label Content="{Binding Name}" />
<!-- DataContext is still ClassA, however we are
setting it to ClassA.ClassB with a binding -->
<StackPanel DataContext="{Binding ClassB}">
<!-- DataContext inherited from parent, which is
ClassB, so this will display ClassB.Name -->
<Label Content="{Binding Name}" />
<!-- DataContext is still ClassB, but we are
binding to the Window's DataContext.Name,
which is ClassA.Name -->
<Label Content="{Binding
ElementName=MyWindow,
Path=DataContext.Name}" />
</StackPanel>
<!-- We've left the StackPanel with its DataContext
bound to ClassB, so this Label's DataContext
is ClassA (inherited from parent StackPanel),
and we are binding to ClassA.ClassB.Name -->
<Label Content="{Binding ClassB.Name}" />
</StackPanel>
</Window>
是的,您的用户控件可以具有 DataContext,并且该用户控件中的任何控件也可以具有不同的 DataContext,但在您的方案中,这不是您应该执行的操作。
您的 TextBox 应使用绑定到 UserControl 的基础 ViewModel 的简单命令,并且在执行该命令时,应使用消息总线从 MainViewModel 或任何其他 ViewModel 获取所需的任何内容。消息总线是 ViewModels 应该在 MVVM 中通信和交换信息的方式。