简体   繁体   English

WPF MVVM-从子视图模型更新MainView的Datagrid

[英]WPF MVVM - Update Datagrid of the MainView from a child viewmodel

I think it may be quite simple but I have been googling a solution for a while without success, and I am not sure what is the correct approach. 我认为这可能很简单,但是一段时间以来我一直在寻找解决方案,但没有成功,而且我不确定什么是正确的方法。 I saw that Prism could be a solution but I am looking for something simple. 我看到Prism可能是一个解决方案,但我正在寻找简单的方法。

I have a MainViewModel and a MainView which contains a Datagrid. 我有一个MainViewModel和一个包含Datagrid的MainView。 The MainView contains also a ContentControl which display a ChildView (with DataContext as ChildViewModel). MainView还包含一个ContentControl,它显示一个ChildView(以DataContext作为ChildViewModel)。

I use DataTemplate to associate Views and ViewModels. 我使用DataTemplate关联视图和ViewModels。

The DataGrid of the MainView is Binded to an ObservableCollection of the ChildViewModel. MainView的DataGrid绑定到ChildViewModel的ObservableCollection。

I want this DataGrid to be updated every time this Collection is modified. 我希望每次修改此Collection时都更新此DataGrid。 I have tried to use the INotifyPropertyChanged. 我试图使用INotifyPropertyChanged。 I have tried to use the OnCollectionChanged. 我试图使用OnCollectionChanged。

When I debug I can see that the Collection has changed and that event is fired but how to refresh the binding ? 当我调试时,可以看到Collection发生了更改,并且触发了该事件,但是如何刷新绑定? (dataGrid is not updated). (未更新dataGrid)。

Here is the code: 这是代码:

DataTemplate DataTemplate中

<DataTemplate DataType="{x:Type vm:ChildViewModel}">
    <vi:ChildView />
</DataTemplate>

XAML MainView XAML主视图

     <ContentControl Content="{Binding childViewModel}"/>

     <DataGrid x:Name="DataGridChildren"
                       ItemsSource="{Binding childViewModel.Children,Mode=TwoWay}" 
                       SelectedItem="{Binding childViewModel.SelectedItem}" EnableRowVirtualization="True" IsReadOnly="True" AutoGeneratingColumn="DataGrid_AutoGeneratingColumn">

MainViewModel MainViewModel

public ChildViewModel childViewModel { get; set; }

public MainViewModel()
{
    childViewModel = new ChildViewModel();
}

ViewModelBase ViewModelBase

public abstract class ViewModelBase : INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
        {
            var handler = PropertyChanged;
            handler?.Invoke(this, args);
        }
    }

ChildViewModel ChildViewModel

 public class ChildViewModel: ViewModelBase
    {
        private ObservableCollection<Child> _Children;
        public ObservableCollection<Child> Children
        {
            get { return _Children; }
            set
            {
                _Children = value;
                OnPropertyChanged("Children");
                _Children.CollectionChanged +=handler;   
            }
        }

        private void handler(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            //What to do ?
        }

        public ChildViewModel()
        {
            Children = new ObservableCollection<Child>(ChildService.GetAllChild());
        }`    

Edit @lezhkin11 编辑@ lezhkin11

Yes I think that is the problem. 是的,我认为这是问题所在。 But I have no idea how to fix it 但我不知道如何解决

Code behind MainView MainView背后的代码

void MainView_Loaded(object sender, RoutedEventArgs e)
{  
    mainViewModel = new MainViewModel();
    DataContext = mainViewModel;
}

Code behind ChildView ChildView背后的代码

void ChildView_Loaded(object sender, RoutedEventArgs e)
{
     childViewModel = new ChildViewModel();
     DataContext = childViewModel;
}

A button allow to do a new search: 按钮允许进行新的搜索:

 private void BtnRefresf_Click(object sender, RoutedEventArgs e) // Search
 {
      childViewModel.Search();
 }

Then a method in the childViewModel will use the service to give a new value to the Observable collection (when I debug, I can reach the OnpropertyChanged of the collection) 然后childViewModel中的方法将使用该服务为Observable集合赋予新值(当我调试时,我可以到达该集合的OnpropertyChanged)

   public void Search()
     {
            ObservableCollection<Child> collec = new ObservableCollection<Child>(ChildService.GetAllChild());

            Children = collec;
    }

Your DataGrid is bound to ChildViewModel inside MainViewModel (instance 1). 您的DataGrid绑定到MainViewModel内部的ChildViewModel (实例1)。 While ChildView has it's own ChildViewModel (instance 2). 虽然ChildView有它自己的ChildViewModel (实例2)。

You have to make sure that both controls reference to the same instance. 您必须确保两个控件都引用同一实例。

1) Remove completely public ChildViewModel childViewModel { get; set; } 1)完全删除public ChildViewModel childViewModel { get; set; } public ChildViewModel childViewModel { get; set; } public ChildViewModel childViewModel { get; set; } from MainViewModel public ChildViewModel childViewModel { get; set; }来自MainViewModel

2) Give a name to the ChildView. 2)给ChildView命名。

<vi:ChildView x:Name="MyChild" />

3) Bind DataGrid's properties to correct view-model 3)绑定DataGrid的属性以更正视图模型

 <DataGrid ItemsSource="{Binding DataContext.Children, ElementName=MyChild, Mode=TwoWay}" />

Also, I would recommend initializing DataContext directly in constructor. 另外,我建议直接在构造函数中初始化DataContext。 Loaded event is too late - as result you always have lot's of XAML binding exceptions that affect performance (even can lead to unexpected behavior) 加载的事件为时已晚-结果您总是会有很多XAML绑定异常会影响性能(甚至可能导致意外行为)

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

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