我在MVVM模式中使用WPF。我正在使用实体框架。我有一个带有选项卡控件的主窗口(Entitlements视图)。此视图中的选项卡项目均绑定到用户控件的视图。
权利观点:
<TabControl Grid.Row="1">
<TabItem Header="Accounts" Content="{Binding AccountsViewModel}"/>
<TabItem Header="Users" Content="{Binding UsersViewModel}"/>
</TabControl>
App.Xaml.cs在初始化时实例化Entitlements视图:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var mainWindow = new MainWindow();
var viewModel = new EntitlementsViewModel();
mainWindow.DataContext = viewModel;
mainWindow.Show();
}
}
DataContext在View Xaml中设置:
xmlns:vm="clr-namespace:DIEntitlements.ViewModels">
<UserControl.Resources>
<vm:AccountsViewModel x:Key="AccountsViewModel"/>
</UserControl.Resources>
<Grid DataContext="{StaticResource AccountsViewModel}">
App.Xaml中的ViewModel DataTemplates:
<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");
}
}
Linq方法:
private void GetUserHeaders()
{
var query = from u in _context.tbUsernames
where u.accountId == SelectedAccountHeader.accountid
select u;
UsersCollection = new ObservableCollection<tbUsername>(query);
}
在第一个选项卡选择中,调用相应的ViewModel构造函数&amp; UI按预期显示。当更改持久保存回数据库但UI未刷新时,会出现此问题。我正在View Models中正确实现INotifyPropertyChanged。我认为这个问题源于只有视图模型和视图的1个实例在初始化时构建,然后保存在内存和放大器中。保持更改时不重新初始化。有没有一种方法可以刷新用户界面而不需要笨重的刷新&#39;按钮&#39;在用户界面?
答案 0 :(得分:0)
从评论开始 - 看起来你正在使用ObservableCollection,但是该集合中的对象没有实现INotifyPropertyChanged,因为它们直接来自数据库。
我建议你需要另一层,你可以转换这些&#39; POCO&#39;将对象转换为实现INotifyPropertyChanged的类。您可以继承BindableBase。要使用它创建属性,属性将如下所示:
private int _displayNumber;
public int DisplayNumber
{
get { return _displayNumber; }
set { SetProperty(ref _displayNumber, value); }
}
如果您无法完成所有转换操作,可以使用AutoMapper进行转移。
所以一般的流程是:
...然后反过来将它送回数据库。
答案 1 :(得分:0)
经过多次修补后,我已经解决了这个问题。
这是我的RefreshEntities()方法,它调用MergeOption.OverwriteChanges;它基本上覆盖了上下文实体&amp;使用来自DB的新数据重新加载集合。你告诉EF覆盖你传入的实体。我正在调用这个方法,只要我坚持改变那个视图
private void RefreshEntities()
{
var objectContext = ((IObjectContextAdapter)_context).ObjectContext;
var objectSet = objectContext.CreateObjectSet<vwAccountHeader>();
objectSet.MergeOption = MergeOption.OverwriteChanges;
AccountHeaderCollection = new ObservableCollection<vwAccountHeader>(objectSet);
}
看起来非常冗长,但效果很好。我建议您在任何MVVM WPF应用程序中尝试更新UI中的视图,该视图已通过用户与EF框架模型中的关联表的交互而发生更改。基本上表格和表格之间存在交叉关系。一个观点&amp;您需要在UI中更新该视图。
MergeOption.OverwriteChanges会覆盖所有挂起的更改,但您可以使用MergeOption.PreserveChanges将重新加载的值合并到您编辑的值中。