在ViewModel中实体模型更改时更新UI

时间:2013-09-18 04:37:20

标签: c# wpf entity-framework mvvm data-binding

我试图想出一个使用Entity-Framework实现MVVM模式的好方法,其中我的实体是我的模型。我的DataContext是我的视图模型。这是对问题的一个小小的再现。

查看

<TextBox Text="{Binding MyText}" />

视图模型

我需要从我的数据库中按记录导航记录。在View中单击按钮时,会将命令发送到执行nextRecord()的Viewmodel。 EF发挥其神奇作用,_myObject是数据库中的下一行/记录

public class myViewModel: INotifyPropertyChanged
{
    private MyEntityObject _myObject;

    public string MyText
    {
        get { return _myObject.MyText; }
        set
        {
            if (_myObject.MyText != value)
            {
                _myObject.MyText = value;
                OnPropertyChanged("MyText");
            }
        }
    }

    private void _nextRecord()
    {
      _myObject = myEntitiesContext.NextRecord() //pseudocode
    }
}

自动生成的实体模型

public partial class MyEntityObject
{
     public string MyText { get; set; }
}

由于View不知道_myObject更改,因此_myObject更改时不会更新。我想到的一些方法。

  1. 我没有测试在INotifyPropertyChanged包装器类中包装我的实体,但我很谨慎,因为我有很多实体对象。

  2. 我可以为所有属性调用OnPropertyChanged("..."),但是我的一些实体对它们有很多属性,这很难看。可以使用反射使其更清晰,但我可能具有不是数据绑定的属性。

  3. 我可能会将此推迟到用户界面,当我点击“下一个记录”时,以某种方式刷新绑定,但这会破坏MVVM并且看起来很脏

  4. 如何让用户界面识别来自_myObject的更改?

4 个答案:

答案 0 :(得分:5)

正如我在评论中提到的,调用OnPropertyChanged("")OnPropertyChanged(null)会使所有属性无效,相当于为每个属性调用OnPropertyChanged。此行为也是documented here

  

PropertyChanged事件可以指示对象上的所有属性   已使用null或String.Empty作为属性名称进行更改   在PropertyChangedEventArgs。

这意味着您可以在更新对象时简单地添加对OnPropertyChanged("")的调用,以强制WPF重新评估视图模型的所有绑定:

private void _nextRecord()
{
    _myObject = myEntitiesContext.NextRecord();
    OnPropertyChanged("");
}

话虽这么说,我仍然会选择@Anand的解决方案(+1)。关于viewmodel是否可以将模型公开为属性是一件正在进行的争论,我倾向于将它暴露出来,直到你需要引入一些特定于视图模型的逻辑。大部分时间你都不需要,并且不值得包装模型属性。

答案 1 :(得分:3)

您的代码存在的问题是,当_myObject更改MyText属性时,不会触发更改事件。解决方法是创建一个新属性来保存实体 并在视图中将此属性设为Grid DataContext,如下所示。现在,当执行此行MyObject = myEntitiesObject.NextRecord()时,您的视图将会收到有关更改的通知。

public class myViewModel : INotifyPropertyChanged
{

    private MyEntityObject _myObject;

    public MyEntityObject MyObject
    {
        get { return _myObject; }
        set {
            if (_myObject != value)
            {
                _myObject = value;
                OnPropertyChanged("MyObject");
            }
        }
    }


    private void _nextRecord()
    {
      MyObject = myEntitiesObject.NextRecord() //pseudocode
    }
}

查看:

    <Grid DataContext="{Binding MyObject}"> 
        <TextBlock Text="{Binding MyText}"/>
    </Grid>

答案 2 :(得分:0)

一个非常简单但不太优雅的解决方案,我相信它会满足需要:在切换记录时,将DataContext设置为null,然后再返回ViewModel。

然而,可以说更优雅的替代品需要更多的工作来满足所有要求。请参阅Anand的答案以获得改进。

答案 3 :(得分:-1)

View中的标记应该具有设置值的模式和UpdateSourceTrigger属性。