You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中ContentControl内DataGrid无法随ObservableCollection动态更新问题

WPF DataGrid动态加载数据不更新问题解决

问题核心

你的代码存在两个关键问题导致DataGrid不更新:

  1. DemoView创建了独立的ViewModel实例:DemoView中显式设置UserControl.DataContext为新的ViewModel,这使得它绑定的集合和MainWindow中ViewModel的Persons不是同一个实例——构造函数里显示的数据是DemoView自身ViewModel的集合,而LoadData操作的是MainWindow的ViewModel的集合,两者完全无关。
  2. 绑定上下文不匹配:通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 21:05:22