Reputation:
I have a question about how WPF MVVM works and have working code but not sure why it's working. Most of the tutorials online seem to give examples using a single Window so I'm not sure if I'm doing this correctly with multiple windows/pages/usercontrols.
If I have a class named ViewModel
and I set the DataContext
in MainWindow
using the code below, then I've set the DataContext
of the MainWindow
only.
MainWindow.xaml.cs:
public partial class MainWindow
{
Private ViewModel viewModel = new ViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = this.viewModel;
}
}
If I then create a new usercontrol and then bind a DataGrid without specifying a path to the viewModel, why does the code below work when I haven't set the DataContext
of the usercontrol?
Is this how WPF works or should I also be setting the DataContext in the usercontrol? What is the correct method to do this?
MainSignals.xaml:
<UserControl x:Class="ProjectXYZ.Content.MainSignals"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:core="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:ProjectXYZ.Content"
xmlns:mui="http://firstfloorsoftware.com/ModernUI"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" >
<Grid>
<DockPanel>
<DataGrid Name="DG1" ItemsSource="{Binding ReceivedSignals}" >
<DataGrid.Columns>
<mui:DataGridTextColumn Header="SignalID" Binding="{Binding signalID}"/>
<mui:DataGridTextColumn Header="SignalType" Binding="{Binding signalType}"/>
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</Grid>
</UserControl>
ViewModel.cs:
private ObservableCollection<MainWindow.SignalVar> _receivedSignals;
Public ViewModel()
{
}
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
public ObservableCollection<MainWindow.SignalVar> ReceivedSignals
{
get { return _receivedSignals; }
set
{
if (value != _receivedSignals)
{
_receivedSignals = value;
OnPropertyChanged("ReceivedSignals");
}
}
}
UserControl.xaml.cs:
public partial class MainSignals : UserControl
{
public MainSignals()
{
InitializeComponent();
//this.DataContext = new ViewModel(); //WORKS WITHOUT THIS??
}
}
Upvotes: 0
Views: 1871
Reputation: 18578
This is due to the fact that child control inherit the DataContext
of their parent if their DataContext
is not set explicitly. This is true for some of the DependancyProperties
e.g if you set the Foreground of parent control all the child control inherit the same value of Foreground property.
In your case, as you have not set the DataContext
explicitly for the child UserControl, it will take the DataContext of its parent, which is your Window here.
Upvotes: 2