【发布时间】:2019-01-19 05:29:43
【问题描述】:
我认为这可能很简单,但我在谷歌上搜索了一段时间没有成功,我不确定什么是正确的方法。我看到 Prism 可能是一个解决方案,但我正在寻找一些简单的东西。
我有一个 MainViewModel 和一个包含 Datagrid 的 MainView。 MainView 还包含一个 ContentControl,它显示一个 ChildView(DataContext 作为 ChildViewModel)。
我使用 DataTemplate 来关联 View 和 ViewModel。
MainView 的 DataGrid 绑定到 ChildViewModel 的 ObservableCollection。
我希望每次修改此集合时都更新此 DataGrid。 我曾尝试使用 INotifyPropertyChanged。 我尝试使用 OnCollectionChanged。
当我调试时,我可以看到 Collection 已更改并且该事件已触发但如何刷新绑定? (dataGrid 未更新)。
代码如下:
数据模板
<DataTemplate DataType="{x:Type vm:ChildViewModel}">
<vi:ChildView />
</DataTemplate>
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">
主视图模型
public ChildViewModel childViewModel { get; set; }
public MainViewModel()
{
childViewModel = new ChildViewModel();
}
视图模型库
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);
}
}
子视图模型
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());
}`
编辑@lezhkin11
是的,我认为这就是问题所在。但我不知道如何解决它
MainView 后面的代码
void MainView_Loaded(object sender, RoutedEventArgs e)
{
mainViewModel = new MainViewModel();
DataContext = mainViewModel;
}
ChildView 背后的代码
void ChildView_Loaded(object sender, RoutedEventArgs e)
{
childViewModel = new ChildViewModel();
DataContext = childViewModel;
}
允许进行新搜索的按钮:
private void BtnRefresf_Click(object sender, RoutedEventArgs e) // Search
{
childViewModel.Search();
}
然后childViewModel中的一个方法会使用服务给Observable集合一个新的值(我调试的时候可以到达集合的OnpropertyChanged)
public void Search()
{
ObservableCollection<Child> collec = new ObservableCollection<Child>(ChildService.GetAllChild());
Children = collec;
}
【问题讨论】:
-
您使用的逻辑是正确的。我怀疑问题出在
。您只需创建视图和视图模型的另一个实例。因此,您的数据网格绑定到 ChildViewModel 的一个实例,而 ChildView 绑定到另一个实例。这只是一个假设。您能否提供 ChildView 的代码隐藏、其 XAML 以及添加新项目的位置 -
实际上,我现在正在尝试完全更新该系列。我已经尝试过 Children.Add(..) 我得到了相同的结果。
-
您有 2 个选项。 1) 删除此方法
ChildView_Loaded并在DataTemplate 中执行<vi:ChildView DataContext="{Binding}" />。 2) 删除public ChildViewModel childViewModel { get; set; },然后删除ContentControl和DataTemplate。你的新 XAML<vi:ChildView x:Name="MyChild" /> <DataGrid ItemsSource="{Binding DataContext.Children, ElementName=MyChild,Mode=TwoWay}" -
谢谢。第一个选项不是很方便,因为我在使用 childviewmodel 的视图上有几个控件。我尝试了第二个,但我得到了错误:Cannot find source for binding with reference 'ElementName=MyChild'
-
它应该可以工作。很简单的场景。看起来您尚未为 ChildView 分配名称。再一次:1)您从 MainViewModel 中删除 ChildViewModel 属性。 2)然后你在XAML中删除ContentControl和DataTemplate 3)直接在XAML中创建ChildView并为其分配名称
x:Name="MyChild"。