简体   繁体   English

WPF MVVM - 将多个视图/视图模型绑定到同一个基本视图模型

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

I have a WPF application using MVVM pattern.我有一个使用 MVVM 模式的 WPF 应用程序。 There is a view that has 5-6 tabs along the top.有一个视图,顶部有 5-6 个选项卡。 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.每个选项卡视图中的 forms 几乎相同,其中几个只有一个附加字段。 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我现在尝试使用的实现包括使用“BaseViewModel”,其中包括这样的属性

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然后,各个选项卡的 ViewModel 从 BaseViewModel 继承并包含这样的代码

        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.我需要将这些 go 放入单个选项卡 ViewModels 中,因为它们的每个 RefreshProjectList 方法将应用略有不同的逻辑,因此我无法将第二个代码块放入 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.当一个选项卡填写表单时,BaseViewModel 的属性似乎发生了变化,但是当我切换到另一个选项卡时,尽管表单的 ComboBox 被赋予了绑定,但表单并未使用来自 Base 的值填写。

ComboBox binding in xaml example: ComboBox 绑定在 xaml 示例中:

        <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.如果您使用所需的数据属性制作 class,则可以在行为类中将它们代理出来。

    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.注意这将触发一个以MyData作为发送者的事件,如果您希望 ViewModel 成为发送者,则需要实现INotifyPropertyChanged ,侦听该事件并使用新的发送者调用外部事件。 You will then need to implement IDisposable where you dispose the listener.然后,您需要在处置侦听器的地方实现IDisposable

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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