简体   繁体   中英

WPF MVVM - Binding multiple View/ViewModels to same base ViewModel

I have a WPF application using MVVM pattern. There is a view that has 5-6 tabs along the top. Each of these tabs is a view that includes a form and then data loads into the view below the form.

The forms in each tabbed view are nearly identical, with a couple of them just having one additional field. I would like to make it so that when a user fills out a form on one tab, when you switch to another tab, the form values will be automatically be carried over with what you've input in the other tabs.

The implementation I'm attempting to use right now includes uses a "BaseViewModel" that includes properties like this

private string _SelectedProjectCollection;

        public string SelectedProjectCollection
        {
            get => _SelectedProjectCollection;
            set
            {
                _SelectedProjectCollection = value;
                OnPropertyChanged(nameof(SelectedProjectCollection));
            }
        }

The ViewModels for the individual tabs then inherit from the BaseViewModel and include code like this

        public string SelectedProjectCollection
        {
            get => base.SelectedProjectCollection;
            set
            {
                base.SelectedProjectCollection = value;
                OnPropertyChanged(nameof(SelectedProjectCollection));
                if (value != null)
                {
                    RefreshProjectList();
                }
            }
        }

I need these to go into the individual tab ViewModels because each of their RefreshProjectList methods will apply slightly different logic, so I cannot put the second code block into the BaseViewModel.

I've put breakpoints in to monitor the data flow. The BaseViewModel's properties appear to change when one tab fills out the form, but when I switch to another tab, the form is not filled out with the values from the Base, despite the form's ComboBox being given the Binding.

ComboBox binding in xaml example:

        <ComboBox Grid.Row="0" Grid.Column="0" materialDesign:HintAssist.Hint="Project Collection" IsEditable="True" Style="{StaticResource MaterialDesignFloatingHintComboBox}" ItemsSource="{Binding Path=ProjectCollectionList}" SelectedItem="{Binding Path=SelectedProjectCollection, Mode=TwoWay}"></ComboBox>

Any advice pulling me in the right direction here would be greatly appreciated.

One approach to this would be to use composition. If you make a class with the data properties you need, you can proxy them out in your behavioral classes.

    public class MyData : INotifyPropertyChanged
    {
        private string _myProp;

        public string MyProp
        {
            get => _myProp;
            set
            {
                _myProp = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class ViewModel : INotifyPropertyChanged
    {
        private readonly MyData _data;

        public ViewModel(MyData data)
        {
            _data = data;
        }

        public string MyProp
        {
            get => _data.MyProp;
            set => _data.MyProp = value;
        }

        public event PropertyChangedEventHandler PropertyChanged
        {
            add => _data.PropertyChanged += value;
            remove => _data.PropertyChanged -= value;
        }
    }

Note This will fire an event with MyData as sender, if you want the ViewModel to be the sender you will need to implement INotifyPropertyChanged , listen to the event and invoke the outer event with the new sender. You will then need to implement IDisposable where you dispose the listener.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM