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

WPF视图切换数据丢失求助:添加人员后DataGrid无数据

WPF视图切换时数据丢失问题解决方案

问题描述

开发WPF项目时,主窗口通过左侧按钮切换右侧ContentControl的视图:

  • 一个视图是添加人员表单,绑定ObservableCollection<PersonModel>的DataGrid能正常显示新增数据
  • 切换到展示人员的DataGrid视图时,仅显示表头,无人员数据

核心原因

  1. ViewModel实例独立:每次切换视图时,NavigationViewModel都会创建新的AddPeopleViewModel和DisplayPeopleViewModel实例,两个实例的People集合完全分离,新增数据只存在于当前AddPeopleViewModel中,展示视图的新实例集合为空。
  2. UserControl硬编码DataContext:两个视图内部直接设置DataContext为新ViewModel实例,覆盖了ContentControl传递的ViewModel,导致绑定的是独立的局部实例。

修复步骤

1. 移除UserControl内部的DataContext设置

分别修改AddPeopleView和DisplayPeopleView的XAML,删除<UserControl.DataContext>节点,让视图继承ContentControl传递的ViewModel:

修改后的AddPeopleView

<UserControl x:Class="SwitchViewsDemo2.Views.AddPeopleView"
             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:vm="clr-namespace:SwitchViewsDemo2.ViewModels"
             mc:Ignorable="d" FontSize="28"
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"/>
            <RowDefinition Height="2*"/>
        </Grid.RowDefinitions>

        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

            <TextBlock Text="Add People" />

            <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
                <TextBlock Text="First Name" />
                <TextBox Text="{Binding FirstName}"/>
            </StackPanel>

            <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Column="1">
                <TextBlock Text="Last Name" />
                <TextBox Text="{Binding LastName}"/>
            </StackPanel>
        </Grid>

        <StackPanel Grid.Row="1">
            <Button Content="Add Person" Command="{Binding AddPersonCommand}"
                Height="40" Width="200" VerticalAlignment="Top"/>
            <DataGrid ItemsSource="{Binding People}"/>
        </StackPanel>
    </Grid>
</UserControl>

修改后的DisplayPeopleView

<UserControl x:Class="SwitchViewsDemo2.Views.DisplayPeopleView"
             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:vm="clr-namespace:SwitchViewsDemo2.ViewModels"
             mc:Ignorable="d" FontSize="28"
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <StackPanel>
            <TextBlock Text="Display People"/>
            <DataGrid ItemsSource="{Binding People}"/>
        </StackPanel>  
    </Grid>
</UserControl>

2. 创建共享数据源

新建PeopleRepository类管理全局共享的人员集合:

using SwitchViewsDemo2.Models;
using System.Collections.ObjectModel;

namespace SwitchViewsDemo2.Models
{
    public class PeopleRepository
    {
        public ObservableCollection<PersonModel> People { get; } = new ObservableCollection<PersonModel>();
    }
}

3. 修改ViewModelBase,移除独立集合

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace SwitchViewsDemo2.Utilities
{
    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler? PropertyChanged;
        public void OnPropertyChanged([CallerMemberName] string propName = null) => 
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    }
}

4. 更新NavigationViewModel,注入共享数据源

using SwitchViewsDemo2.Models;
using SwitchViewsDemo2.Utilities;
using System.Windows.Input;

namespace SwitchViewsDemo2.ViewModels
{
    public class NavigationViewModel : ViewModelBase
    {
        private readonly PeopleRepository _peopleRepo;
        private object _currentView;

        public object CurrentView
        {
            get { return _currentView; }
            set { _currentView = value; OnPropertyChanged(); }
        }

        public ICommand GoToAddPeopleCommand { get; set; }
        public ICommand GoToDisplayPeopleCommand { get; set; }

        private void AddPeople(object obj) => CurrentView = new AddPeopleViewModel(_peopleRepo);
        private void DisplayPeople(object obj) => CurrentView = new DisplayPeopleViewModel(_peopleRepo);

        public NavigationViewModel()
        {
            _peopleRepo = new PeopleRepository();
            GoToAddPeopleCommand = new RelayCommand(AddPeople);
            GoToDisplayPeopleCommand = new RelayCommand(DisplayPeople);
            CurrentView = new AddPeopleViewModel(_peopleRepo);
        }
    }
}

5. 更新AddPeopleViewModel,绑定共享集合

using SwitchViewsDemo2.Models;
using SwitchViewsDemo2.Utilities;
using System.Collections.ObjectModel;

namespace SwitchViewsDemo2.ViewModels
{
    public class AddPeopleViewModel : ViewModelBase
    {
        private readonly PeopleRepository _peopleRepo;
        private string _firstName;

        public string FirstName
        {
            get { return _firstName; }
            set { _firstName = value; OnPropertyChanged(); }
        }

        private string _lastName;

        public string LastName
        {
            get { return _lastName; }
            set { _lastName = value; OnPropertyChanged(); }
        }

        public ObservableCollection<PersonModel> People => _peopleRepo.People;

        public ButtonCommand AddPersonCommand { get; set; }

        public void AddPerson()
        {
            PersonModel p = new PersonModel()
            {
                FirstName = FirstName,
                LastName = LastName
            };

            FirstName = string.Empty;
            LastName = string.Empty;
            People.Add(p);
        }

        public AddPeopleViewModel(PeopleRepository peopleRepo)
        {
            _peopleRepo = peopleRepo;
            AddPersonCommand = new ButtonCommand(AddPerson);
        }
    }
}

6. 更新DisplayPeopleViewModel,绑定共享集合

using SwitchViewsDemo2.Models;
using SwitchViewsDemo2.Utilities;
using System.Collections.ObjectModel;

namespace SwitchViewsDemo2.ViewModels
{
    public class DisplayPeopleViewModel : ViewModelBase
    {
        private readonly PeopleRepository _peopleRepo;

        public ObservableCollection<PersonModel> People => _peopleRepo.People;

        public DisplayPeopleViewModel(PeopleRepository peopleRepo)
        {
            _peopleRepo = peopleRepo;
        }
    }
}

修复效果

现在切换视图时,两个ViewModel共享同一个PeopleRepository中的ObservableCollection,新增人员后切换到展示视图,DataGrid会正常显示所有已添加的数据。

内容的提问来源于stack exchange,提问作者Ricman1029

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 03:55:25