Question

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??
    }

}
Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top