Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF MVVM - Binding properties on UserControls to ViewModel of container

Tags:

mvvm

binding

wpf

I have a Window (MainWindow.xaml) which has a ViewModel (MainWindowViewModel.cs). I also have a UserControl called MyUserControl.xaml which also has a corresponding ViewModel (MyUserControlViewModel.cs).

I have inserted two instances of the UserControl into the MainWindow:

<Window x:Class="MyProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyProject"
    Title="My Window">
    <Grid>
        <local:MyUserControl Visibility="{Binding Path=MyUserControl1Visibility, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
        <local:MyUserControl Visibility="{Binding Path=MyUserControl2Visibility, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
    </Grid>
</Window>

In the CodeBehind of MainWindow I set the DataContext of the Window to an instance of the ViewModel:

public MainWindow()
{
    InitializeComponent();
    this.DataContext = new MainWindowViewModel();
}

MainWindowViewModel has the Visibility-properties that the MyUserControl-instances are bound to. They both look like this:

private Visibility _myUserControl1Visibility = Visibility.Collapsed;
public Visibility MyUserControl1Visibility
{
    get
    {
        return _myUserControl1Visibility;
    }
    private set
    {
        if (value != _myUserControl1Visibility)
        {
            _myUserControl1Visibility = value;
            OnPropertyChanged("MyUserControl1Visibility");
        }
    }
}

Furthermore, MainWindow and MainWindowViewModel has buttons and commands to enable the user to toggle between the two MyUserControl instances. That is, only one of them are shown at any time.

This worked fine… until the UserControls got their own ViewModels. Now the runtime tries to find the bound VisibilityProperties (MyUserControl1Visibility…) on the ViewModels of the UserControls instead of the ViewModel of MainWindow.

How do I make these bindings go to MainWindowViewModel instead of to the respective ViewModels of the UserControl instances?

like image 565
haagel Avatar asked Dec 09 '10 19:12

haagel


2 Answers

The MyUserControls inherited the DataContext from MainWindow and that's why it works to begin with. When MyUserControl1 get a ViewModel of its own that will be its DataContext. Maybe this was clear to you :) To use the DataContext of the MainWindow in the binding instead you can use RelativeSource or name the Window and use ElementName

<local:MyUserControl Visibility="{Binding ElementName=mainWindow, 
                                          Path=DataContext.MyUserControl1Visibility,
                                          Mode=OneWay,
                                          UpdateSourceTrigger=PropertyChanged}" />
like image 111
Fredrik Hedblad Avatar answered Nov 07 '22 18:11

Fredrik Hedblad


Visibility="{Binding RelativeSource={x:Static RelativeSource.Self},
            Path=DataContext.MyUserControl1Visibility}"
like image 26
Ben Avatar answered Nov 07 '22 20:11

Ben