C# WPF MVVM:用户控件视图未在CRUD上刷新?
我在MVVM模式中使用WPF。我使用的是实体框架。我有一个带有选项卡控件的主窗口(授权视图)。此视图中的选项卡项都绑定到作为用户控件的视图 权利视图:C# WPF MVVM:用户控件视图未在CRUD上刷新?,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我在MVVM模式中使用WPF。我使用的是实体框架。我有一个带有选项卡控件的主窗口(授权视图)。此视图中的选项卡项都绑定到作为用户控件的视图 权利视图: <TabControl Grid.Row="1"> <TabItem Header="Accounts" Content="{Binding AccountsViewModel}"/> <TabItem Header="Users" Content="{Binding Users
<TabControl Grid.Row="1">
<TabItem Header="Accounts" Content="{Binding AccountsViewModel}"/>
<TabItem Header="Users" Content="{Binding UsersViewModel}"/>
</TabControl>
DataContext在视图Xaml中设置:
xmlns:vm="clr-namespace:DIEntitlements.ViewModels">
<UserControl.Resources>
<vm:AccountsViewModel x:Key="AccountsViewModel"/>
</UserControl.Resources>
<Grid DataContext="{StaticResource AccountsViewModel}">
xmlns:vm=“clr名称空间:DIEntitlements.ViewModels”>
App.Xaml中的ViewModel数据模板:
<ResourceDictionary>
<DataTemplate DataType="{x:Type vm:AccountsViewModel}">
<v:AccountsView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:UsersViewModel}">
<v:UsersView/>
</DataTemplate>
</ResourceDictionary>
&最后是一段ViewModel代码:
财产:
private ObservableCollection<tbUsername> _usersCollection;
public ObservableCollection<tbUsername> UsersCollection
{
get { return _usersCollection; }
set
{
_usersCollection = value;
OnPropertyChanged("UsersCollection");
}
}
private observeCollection\u userscolection;
公共可见集合用户集合
{
获取{return\u userscolection;}
设置
{
_usersCollection=值;
OnPropertyChanged(“UsersCollection”);
}
}
Linq方法:
private void GetUserHeaders()
{
var query = from u in _context.tbUsernames
where u.accountId == SelectedAccountHeader.accountid
select u;
UsersCollection = new ObservableCollection<tbUsername>(query);
}
private void GetUserHeaders()
{
var query=来自_context.tbUsernames中的u
其中u.accountId==SelectedAccountHeader.accountId
选择u;
UsersCollection=新的ObservableCollection(查询);
}
在选择第一个选项卡时,将调用相应的ViewModel构造函数&UI将按预期显示。当更改被持久化回数据库,但UI未刷新时,就会出现问题。我正在视图模型中正确地实现INotifyPropertyChanged。我认为这个问题是由于在初始化时只构建了视图模型和视图的1个实例,然后将其保存在内存中&当更改被持久化时,不会重新初始化。有没有一种方法可以刷新UI而不必在UI中使用笨重的“刷新”按钮?从注释中可以看出-看起来您正确使用了ObservableCollection,但是该集合中的对象没有实现INotifyPropertyChanged,因为它们直接来自数据库 我建议您需要另一个层,将这些“POCO”对象转换为实现INotifyPropertyChanged的类。你可以继承他的遗产。要使用它创建属性,属性将如下所示:
private int _displayNumber;
public int DisplayNumber
{
get { return _displayNumber; }
set { SetProperty(ref _displayNumber, value); }
}
如果你不想费心去做所有的转换,你可以用它来做转换
因此,一般流程是:
…然后反向返回到数据库。经过多次修补,我已经解决了这个问题 下面是我的RefreshEntities()方法,它调用MergeOption.OverwriteChanges;这实质上覆盖了上下文实体&使用数据库中的新数据重新加载集合。您告诉EF覆盖您传入的实体。无论在何处持久化对该视图的更改,我都会调用此方法
private void RefreshEntities()
{
var objectContext = ((IObjectContextAdapter)_context).ObjectContext;
var objectSet = objectContext.CreateObjectSet<vwAccountHeader>();
objectSet.MergeOption = MergeOption.OverwriteChanges;
AccountHeaderCollection = new ObservableCollection<vwAccountHeader>(objectSet);
}
private void RefreshEntities()
{
var objectContext=((IObjectContextAdapter)_context).objectContext;
var objectSet=objectContext.CreateObjectSet();
objectSet.MergeOption=MergeOption.OverwriteChanges;
AccountHeaderCollection=新的ObservableCollection(objectSet);
}
看起来很冗长,但效果很好。对于任何MVVM WPF应用程序,如果您试图更新UI中的视图,而该视图因用户与EF框架模型中的关联表的交互而发生更改,我建议您这样做。实际上,如果表和视图之间存在交叉关系,则需要在UI中更新该视图
MergeOption.OverwriteChanges覆盖所有挂起的更改,但您可以使用MergeOption.PreserveChanges将重新加载的值合并为编辑后的值。尽管您提供了大量信息,但对虚拟机进行一次嗅探将有助于完整描述。我注意到你有“账户”(复数)。您是否使用了IEnumerable或IList而不是可观察集合之类的东西?IEnumerable和IList不支持更改通知。更改通知是最可能的错误源。此外,尽管看起来很明显,您是否检查了输出窗口中的任何错误?一旦所有内容都绑定正确,您当然不需要刷新按钮。更新了问题@Hockey。是的,我正在使用ViewModel中公开的ObservableCollection属性。除了UI没有自动刷新之外,一切都正常,没有故意丢失视图/视图模型范围并重新初始化。我不确定我是否理解。您的意思是您的
UsersViewModel.UserCollection
正在更改,您希望它触发UsersView的重画?如果是这样的话,只要让您的权限iewmodel向UsersViewModel.PropertyChanged
事件添加一个处理程序,并让它在userscolection属性更改时引发OnPropertyChanged(“UsersViewModel”)
。您有什么收获吗?如果找到答案,为了搜索者的利益,请您发布它:)是的,我理解您关于使用DTO的说法。我的问题是,由于同一个viewModel&view实例被持久化,EF上下文没有被刷新。我需要处理和火灾一个新的看法,但不知道如何做到这一点!
private void RefreshEntities()
{
var objectContext = ((IObjectContextAdapter)_context).ObjectContext;
var objectSet = objectContext.CreateObjectSet<vwAccountHeader>();
objectSet.MergeOption = MergeOption.OverwriteChanges;
AccountHeaderCollection = new ObservableCollection<vwAccountHeader>(objectSet);
}