Reputation: 133
Is it possible to have two different DataContext
in one UserControl? I would like to access one of my Model
objects, but also properties in the MainViewModel. Examples:
ClassDatas DataContext
(an object defined in a Model):
<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>
And further how is it possible to combine them?
<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>
The FieldsTextProperty
is a DataContext
from the MainViewModel
and the EventToCommand
contains DataContext
from my object.
Upvotes: 1
Views: 1577
Reputation: 132548
No, a control can only have a single object set to its DataContext
property
However a binding doesn't have to bind to it's DataContext
. You can use other binding properties to specify a different source for the binding. Commonly used properties to change the source for a binding are Source
, RelativeSource
, and ElementName
.
You can either change the binding's source for a specific binding only, such as you're doing in your Command
binding
Or you can change it for an entire control by setting or binding the control's DataContext
property to something else
I actually see so much confusion over the DataContext
in WPF beginners that I wrote a blog post about it. You may be interested in reading it over : What is this "DataContext" you speak of?
Here's a code block I use to help demonstrate the DataContext
:
Suppose we bind a window to an object called
ClassA
.ClassA
has a property calledClassB
, and bothClassA
andClassB
have a property calledName
.Here is a block of XAML which illustrates how the DataContext works. It also includes an example of how a control would refer to a property not in its own 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>
Upvotes: 2
Reputation: 12119
Yes, your User Control can have a DataContext and any control within that user control can have a different DataContext as well but in your scenario that's not what you should be doing.
Your TextBox should use a simple command bound to the underlying ViewModel of the UserControl and when the command is executed you should use the message bus to get whatever you need from your MainViewModel or any other ViewModel. The message bus is how ViewModels are supposed to communicate and exchange information in MVVM...
Upvotes: 0