Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF MVVM:用户控件视图未在CRUD上刷新?_C#_Wpf_Xaml_Mvvm - Fatal编程技术网

C# WPF MVVM:用户控件视图未在CRUD上刷新?

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

我在MVVM模式中使用WPF。我使用的是实体框架。我有一个带有选项卡控件的主窗口(授权视图)。此视图中的选项卡项都绑定到作为用户控件的视图

权利视图:

  <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); }
}
如果你不想费心去做所有的转换,你可以用它来做转换

因此,一般流程是:

  • 按您正在做的操作获取数据
  • 将其转换为在类中的每个属性上实现INotifyPropertyChanged的类
  • 添加到ObservableCollection
  • 按当前绑定的方式绑定

  • …然后反向返回到数据库。

    经过多次修补,我已经解决了这个问题

    下面是我的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);
        }