是否可以在一个UserControl中使用两个不同的DataContext?

时间:2014-11-25 19:16:25

标签: c# wpf mvvm-light

是否可以在一个UserControl中有两个不同的DataContext?我想访问我的Model个对象之一,还要访问MainViewModel中的属性。例子:

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

MainViewModel 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是来自DataContext的{​​{1}},MainViewModel来自我的对象的EventToCommand

2 个答案:

答案 0 :(得分:0)

是的,您的用户控件可以拥有DataContext,并且该用户控件中的任何控件也可以具有不同的DataContext,但在您的场景中不是您应该执行的操作。

您的TextBox应该使用绑定到UserControl的基础ViewModel的简单命令,并且在执行命令时,您应该使用消息总线从MainViewModel或任何其他ViewModel获取所需的任何内容。消息总线是ViewModels应该如何在MVVM中进行通信和交换信息......

答案 1 :(得分:0)

不,控件只能将单个对象设置为其DataContext属性

但是绑定不会 绑定到它的DataContext。您可以使用其他绑定属性为绑定指定不同的源。用于更改绑定源的常用属性是SourceRelativeSourceElementName

  • 您可以更改特定绑定的绑定源,例如您在Command绑定

  • 中执行的操作
  • 或者您可以通过将控件的DataContext属性设置或绑定到其他内容来为整个控件更改

我实际上在WPF初学者的DataContext看到了很多混乱,我写了一篇关于它的博客文章。您可能有兴趣阅读它:What is this "DataContext" you speak of?

这是我用来帮助演示DataContext

的代码块
  

假设我们将窗口绑定到名为ClassA的对象。 ClassA有一个名为ClassB的属性,ClassAClassB都有一个名为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>