有没有办法在不通知 ItemsSource 集合的情况下使用 ObservableCollection 和 MVVM 刷新 WPF DataGrid?
Posted
技术标签:
【中文标题】有没有办法在不通知 ItemsSource 集合的情况下使用 ObservableCollection 和 MVVM 刷新 WPF DataGrid?【英文标题】:Is there a way to refresh WPF DataGrid using ObservableCollection and MVVM without informing ItemsSource collection? 【发布时间】:2015-09-25 14:52:47 【问题描述】:这是我的第一个问题,所以我会尽力而为。
我正在尝试使用 ObservableCollection 和 MVVM 来“刷新”一个简单的 WPF DataGrid 控件,正如网络上的众多教程所解释的那样。
在上下文中,这些是我的模型类:
(PersonViewModel.cs)
public class PersonViewModel : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private int _id;
private int _idAddress;
private string _name;
private int _age;
private string _address;
public int Id
get return this._id;
set
if (value != this._id)
this._id = value;
OnPropertyChanged();
public int IdAddress
get return this._idAddress;
set
if (value != this._idAddress)
this._idAddress = value;
OnPropertyChanged();
public string Name
get return this._name;
set
if (value != this._name)
this._name = value;
OnPropertyChanged();
public int Age
get return this._age;
set
if (value != this._age)
this._age = value;
OnPropertyChanged();
public string Address
get return this._address;
set
if (value != this._address)
this._address = value;
OnPropertyChanged();
private void OnPropertyChanged([CallerMemberName]String caller = null)
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(caller));
(AddressViewModel.cs)
public class AddressViewModel : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private int _id;
private string _street;
private int _number;
public int Id
get return this._id;
set
if (value != this._id)
this._id = value;
OnPropertyChanged();
public string Street
get return this._street;
set
if (value != this._street)
this._street = value;
OnPropertyChanged();
public int Number
get return this._number;
set
if (value != this._number)
this._number = value;
OnPropertyChanged();
private void OnPropertyChanged([CallerMemberName]String caller = null)
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(caller));
这是数据库模型的表示(无法上传图片
地址
身份证 街道 编号
人
身份证 身份证地址 名称 年龄 Address ---> 此属性连接 Street 和 Number of Address 实体。
所以,如您所见,这是一个非常简单的示例。只是一个概念验证。问题是,每当我尝试向数据库添加新实体时(通过 Entity Framework 6 和 LINQ),我都必须不可避免地将该 ViewModel 实体添加到 DataGrid 的数据上下文中。
这是目前工作的代码:
public static Person CreatePerson(PersonViewModel personVM)
var person = new Person
IdAddress = personVM.IdAddress,
Name = personVM.Name,
Age = personVM.Age
;
try
using (var context = new OCDemoContext())
context.Database.Connection.Open();
context.Person.Add(person);
context.SaveChanges();
context.Database.Connection.Close();
catch
throw;
return person;
如您所见,此处需要在 DataGrid 中显示一列,该列连接 Address 数据库实体的两个属性:Street 和 Number,并将该值赋予 PersonViewModel 类的 Address 属性以在 DataGrid 中显示为一列。
在插入数据库后将实体添加到 DataGrid itemssource 集合的代码:
// Add to the database
PersonsGateway.CreatePerson(personVM);
// Update view on DataGrid's itemssource collection
ViewModel model = this.xGrid.DataContext as ViewModel;
model.Persons.Insert(0, personVM);
XAML 为:
<Window x:Class="OCDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" xmlns:local="clr-namespace:OCDemo">
<Window.Resources>
<local:ViewModel x:Key="xViewModel" />
</Window.Resources>
<Grid x:Name="xGrid" DataContext="StaticResource xViewModel">
<DataGrid x:Name="xDataGrid" Grid.Row="0" ItemsSource="Binding Persons" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="Binding Path=Name" Header="Name"/>
<DataGridTextColumn Binding="Binding Path=Age" Header="Age"/>
<DataGridTextColumn Binding="Binding Path=Address" Header="Address"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
还有 ViewModel.cs
public class ViewModel
public ObservableCollection<PersonViewModel> Persons get; set;
public ViewModel()
this.Persons = PersonsGateway.RetrievePersons();
T4 .tt 文件更新为MSDN - Updating code generation for data binding 解释。
那么,在 ObservableCollection 场景中,是否可以只依赖于将实体添加到数据库而不总是将实体添加到 itemssource 集合?
【问题讨论】:
【参考方案1】:将您的视图模型更改为以下
public class ViewModel
public ObservableCollection<PersonViewModel> Persons get; private set;
public ViewModel()
Persons = new ObservableCollection<PersonViewModel>();
Persons.AddRange(PersonsGateway.RetrievePersons().ToList());
重要的是创建一次可观察集合而不是重新创建它,依赖于更改通知,所以创建它然后使用标准方法来管理它。
【讨论】:
我按照你的建议做了。没有变化。我的目标是直接通过 EF 方法将 PersonViewModel 的新实例添加到数据库中,并且该操作会更新 UI 上的 ViewModel。这可能吗?干杯。【参考方案2】:好的,我应该建议不要使用这段代码
PersonsGateway.CreatePerson(personVM);
ViewModel model = this.xGrid.DataContext as ViewModel;
model.Persons.Insert(0, personVM);
你应该这样做
PersonsGateway.CreatePerson(personVM);
ViewModel model = this.xGrid.DataContext as ViewModel;
model.Persons.Add(personVM);
【讨论】:
事实上,我想做的是不要使用ViewModel model = this.xGrid.DataContext as ViewModel; model.Persons.Add(personVM);
或ViewModel model = this.xGrid.DataContext as ViewModel; model.Persons.Insert(0, personVM);
,只使用PersonsGateway.CreatePerson(personVM);
...或者我必须完全 1.- 插入实体数据库,然后 2.- 更新模型?干杯菲尔
PersonsGateway 是您的 EF 适配器,它与 ObservableCollection 断开连接。您应该有对 Persons 集合所在的父 VM 的引用,因此一旦您知道您已经成功创建了该人,只需添加它,或者完全刷新视图(重建,但是为什么有一个 ObservableCollection)
对不起,我应该彻底阅读您最初的问题,您真正要问的是,您能否让 ObservableCollection 像以前的 DataSet 一样工作,您基本上将数据适配器绑定到它。我不认为你能做到这一点
您通常在这里做的是调用您的服务/存储库,它会返回一个构造的 Person VM,然后您将其添加到您的 ObservableCollection
没错。那是我试图做的。仅依靠网关更新。我必须更好地理解 ObservableCollection 的概念和应用。无论如何,谢谢菲尔:)以上是关于有没有办法在不通知 ItemsSource 集合的情况下使用 ObservableCollection 和 MVVM 刷新 WPF DataGrid?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在不发送推送通知的情况下调用 saveCurrentTurnWithMatchData?
有没有办法在不轮询 REST API 的情况下通知 Google AI Platform 训练作业的状态变化?
有没有办法通过不删除和添加 ItemsSource 来更新 ListBox 的项目? [关闭]