首页 文章

WPF MVVM:用户控制视图在CRUD上没有刷新?

提问于
浏览
0

我在MVVM模式中使用WPF . 我正在使用实体框架 . 我有一个带有选项卡控件的主窗口(Entitlements视图) . 此视图中的选项卡项目均绑定到用户控件的视图 .

enter image description here

权利观点:

<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构造函数,并按预期显示UI . 当更改持久保存回数据库但UI未刷新时,会出现此问题 . 我正在View Models中正确实现INotifyPropertyChanged . 我认为这个问题源于只有视图模型和视图的1个实例在初始化时构造,然后保存在内存中并且在持久化时不重新初始化 . 有没有一种方法可以刷新UI而不需要在UI中使用笨重的“刷新”按钮?

2 回答

  • 0

    继续注释 - 看起来你正在使用ObservableCollection,但是该集合中的对象没有实现INotifyPropertyChanged,因为它们直接来自数据库 .

    我建议您需要另一个图层,将这些'POCO'对象转换为实现INotifyPropertyChanged的类 . 你可以从BindableBase继承 . 要使用它创建属性,属性将如下所示:

    private int _displayNumber;
    
    public int DisplayNumber
    {
      get { return _displayNumber; }
      set { SetProperty(ref _displayNumber, value); }
    }
    

    如果您无法进行所有转换,则可以使用AutoMapper进行转移 .

    所以一般的流程是:

    • 获取正在进行的数据

    • 将其转换为在类中的每个属性上实现INotifyPropertyChanged的类 .

    • 添加到ObservableCollection

    • 绑定,因为您目前正在绑定

    ...然后反过来回到DB的方式 .

  • 0

    我经过多次修补后解决了这个问题 .

    这是我的RefreshEntities()方法,它调用MergeOption.OverwriteChanges;它基本上覆盖了上下文实体,并使用来自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框架模型中的关联表的交互而发生更改 . 基本上,表和视图之间存在交叉关系,您需要在UI中更新该视图 .

    MergeOption.OverwriteChanges会覆盖所有挂起的更改,但您可以使用MergeOption.PreserveChanges将重新加载的值合并到您编辑的值中 .

相关问题