Question

Essentially, I have a main window with a user control on it containing a property which is bound to the view model of the main window. The idea is that when the property changes in the user form that by the binding the property in the main window viewmodel will also change. The problem is that this works when the user control has no ViewModel, when I add a simple ViewModel to the user control, the binding no longer works. And as I need to have a ViewModel for my control I need to work out why adding the ViewModel is breaking the binding and how to fix it. Any suggestions welcomed.

public partial class Control1 : UserControl, INotifyPropertyChanged
{
   public Control1()
    {
        InitializeComponent();
        Loaded += Control1_Loaded;
    }

    void Control1_Loaded(object sender, RoutedEventArgs e)
    {
        DataContext = new Control1ViewModel();
    }

    public static DependencyProperty SavedStringProperty = DependencyProperty.Register(
       "SavedString", typeof(string), typeof(Control1));
    public string SavedString
    {
        get
        {
            return (string)GetValue(SavedStringProperty);
        }
        set
        {
            SetValue(SavedStringProperty, value);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;


    private void FirePropChanged(string property)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property));
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
         SavedString = "Hi";
    }   
}

public class MainWindowViewModel : INotifyPropertyChanged
{
    private string _message = "Hi";
    public string myMessage
    {
        get
        {
          return _message;  
        }
        set
        {
            _message = value;
            FirePropChanged("myMessage");
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;

    private void FirePropChanged(string property)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property));
    }



    private string _savedString;
    public string SavedString
    {
        get
        {
            return _savedString;
        }
        set
        {
            _savedString = value;
            FirePropChanged("SavedString");
        }
    }
}

xaml (in MainWindow) :

<myCtrl:Control1 SavedString="{Binding Path=SavedString, Mode=TwoWay}"/>

cs (my uc viewmode):

 public class Control1ViewModel : INotifyPropertyChanged
 {
      public event PropertyChangedEventHandler PropertyChanged;       
 }
Was it helpful?

Solution

When your UC has it's own Vm i.e. it's own DataContext , you need to climb up the visual tree and refer to it's parent's (Window) DataContext

<myCtrl:Control1 SavedString="{Binding RelativeSource={RelativeSource 
    AncestorType=Window} Path=DataContext.SavedString, Mode=TwoWay}"/>

OTHER TIPS

There's another way to write it with an element name:

SavedStrings="{Binding ElementName=uc_name, Path=DataContext.SavedString}"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top