Search code examples
wpfmvvmuser-controls

WPF -Child datacontext set from the parent ViewModel doesnot contains the modified values in the parent ViewModel


In my WPF application I have a MainWindow.xaml which has many User Controls embedded into it. I have separate viewmodel for both the main window as well as the user controls. In the Main Window ViewModel I create an instance of the child ViewModel and set it as the child's datacontext.

Parent VM ChildUserControlVM ChildVM = new ChildUserControlVM (ParentModel.ChildModel);

MainWindow.xaml

But this approach is not working as I am not getting the values set in the parent viewmodel in the child one and vice versa.

On the contrary, if I set the Child model object as the datacontext from the parent that is working both way.

I need some solution so that I can use MVVM in the user controls also ensuring data gets passed from parent to child and vice versa. In the usercontrol I am going to have some buttons whose action I want to handle in the child Viewmodel through ICommand. Adding the code snippets for reference MainWindow.xaml

<Grid Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0">
    <local:ProfileIdentitySettings Visibility="{Binding ProfileIdentitySettingsVisibility,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" DataContext="{Binding ChildProfileIdentityVM}"/>      
</Grid>

MainWindowVM.cs

 ProfileIdentitySettingsVM ChildProfileIdentityVM = new ProfileIdentitySettingsVM(DeviceEditorModel.ProfileIdentitySettings);

ProfileIdentitySettings.xaml

DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.MainWindowVM}">


Solution

  • My Understanding is like you need to set the usercontrol Viewmodel from MainViewModel.

    MainViewModel:

     public class MainWindowViewModel : INotifyPropertyChanged, IMainViewModel
    {
    
        public MainWindowViewModel()
        {
            this.Collection = new List<string>();
            this.Child = new ChildUserControlViewModel();
            this.Child.mainViewModel = this;
            this.Child.TextValue = "Justin";
        }
        private List<string> _Collection;
    
        public List<string> Collection
        {
            get { return _Collection; }
            set { _Collection = value; this.OnPropertyChanged("Collection"); }
        }
        private string _MainValue;
        public string MainValue
        {
            get { return _MainValue; }
            set { _MainValue = value; this.OnPropertyChanged("MainValue"); }
        }
        private ChildUserControlViewModel child;
        public ChildUserControlViewModel Child
        {
            get { return child; }
            set { child = value; this.OnPropertyChanged("Child"); }
        }
    
    }
    

    Child Usercontrol View model:

    public class ChildUserControlViewModel : INotifyPropertyChanged
    {
    
        public IMainViewModel mainViewModel = null;
    
        public List<string> Collection
        {
            get { return this.mainViewModel.Collection; }
            set { this.mainViewModel.Collection = value; this.OnPropertyChanged("Collection"); }
        }
    
        private string _TextValue;
        public string TextValue
        {
            get { return _TextValue; }
            set
            {
                _TextValue = value;
                this.mainViewModel.MainValue = value;
                this.mainViewModel.Collection.Add(value);
                this.OnPropertyChanged("TextValue");
            }
        }
    }
    
    
    
    
    
     public interface IMainViewModel
        {
            string MainValue { get; set; }
    
             List<string> Collection { get; set; }
        }
    

    View:

    <Grid>
       <usr:ChildUserControl DataContext="{Binding Child}"/>
    </Grid>