WPF中ContentControl内DataGrid无法随ObservableCollection动态更新问题
WPF DataGrid动态加载数据不更新问题解决
问题核心
你的代码存在两个关键问题导致DataGrid不更新:
- DemoView创建了独立的ViewModel实例:DemoView中显式设置
UserControl.DataContext为新的ViewModel,这使得它绑定的集合和MainWindow中ViewModel的Persons不是同一个实例——构造函数里显示的数据是DemoView自身ViewModel的集合,而LoadData操作的是MainWindow的ViewModel的集合,两者完全无关。 - 绑定上下文不匹配:通过DataTemplate显示DemoView时,DemoView的DataContext实际是
DemoViewModel,但DataGrid绑定的Persons属性属于MainWindow的ViewModel,绑定路径无效。
修复步骤
1. 移除DemoView的DataContext声明
打开DemoView的XAML,删除<UserControl.DataContext>节点,让它继承父容器的DataContext(即MainWindow的ViewModel):
<UserControl x:Class="TestINotifyProperty.DemoView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:TestINotifyProperty" d:DataContext="{d:DesignInstance Type=local:ViewModel}" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid> <StackPanel> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Top" Text="Demo View" FontSize="100" FontFamily="courier" Foreground="Blue"/> <DataGrid ItemsSource="{Binding Persons}"/> </StackPanel> </Grid> </UserControl>
2. 优化ViewModel架构(符合MVVM单一职责)
让DemoViewModel持有自己的Persons集合,避免主ViewModel承担过多职责:
修改DemoViewModel:
namespace TestINotifyProperty { public class DemoViewModel : ObservableObject { public ObservableCollection<Model.Person> Persons { get; set; } public DemoViewModel() { Persons = new ObservableCollection<Model.Person>(); // 初始化测试数据 Persons.Add(new Model.Person { Surname= "Doe", Name = "John" }); Persons.Add(new Model.Person { Surname = "Doe", Name = "Jane" }); Persons.Add(new Model.Person { Surname = "Doe", Name = "Baby" }); } } }
修改主ViewModel:
using System.Collections.ObjectModel; namespace TestINotifyProperty { internal class ViewModel : ObservableObject { public RelayCommand LoadData { get; set; } public RelayCommand ChangeView { get; set; } public HomeViewModel HomeVM { get; set; } internal DemoViewModel DemoVM { get; set; } private object _currentView; public object CurrentView { get { return _currentView; } set { _currentView = value; OnPropertyChanged(); } } public ViewModel() { LoadData = new RelayCommand(o => { Load(); }); ChangeView = new RelayCommand(o => { changeView();}); HomeVM = new HomeViewModel(); DemoVM = new DemoViewModel(); CurrentView = HomeVM; } private void Load() { CurrentView = DemoVM; // 直接操作DemoViewModel的Persons集合 DemoVM.Persons.Add(new Model.Person { Surname = "Roe", Name = "Richard" }); DemoVM.Persons.Add(new Model.Person { Surname = "Roe", Name = "Janie" }); } private void changeView() { if (CurrentView == HomeVM) CurrentView = DemoVM; else CurrentView = HomeVM; } } }
为什么之前的解决方案无效?
你尝试的方案可能修改了DataContext传递逻辑,但由于DemoView自行创建了ViewModel实例,绑定的集合始终是独立的,因此无论如何更新主ViewModel的集合,DemoView都无法感知变化。
内容的提问来源于stack exchange,提问作者FraCas
相关产品推荐
相关产品推荐

