【问题标题】:Entity Framework CTP5 Code First, WPF - MVVM modeling实体框架 CTP5 代码优先,WPF - MVVM 建模
【发布时间】:2011-07-01 10:09:21
【问题描述】:

我已经为我的 WPF 应用程序设置了所有模型,并首先使用实体​​框架 ctp5 代码,这是一个示例模型类:

public class Task
{
    public int ID { get; set; }
    public int Index { get; set; }
    public string Content { get; set; }
    public int Indentation { get; set; }
    public DateTime Start { get; set; }
    public decimal Effort { get; set; }
    public decimal CompletedEffort { get; set; }
    public decimal Cost { get; set; }
}

推荐的构建视图模型的方法是什么?我的视图模型将实现 INotifyPropertyChanged,我不希望模型类具有任何特定于 UI 的代码 - 这样它们就可以在其他应用程序中轻松重用。 我应该将所有模型属性设为虚拟然后在视图模型中覆盖它们吗? (似乎有很多不必要的编码......) EF 代码首先会与这种格式很好地配合吗?

编辑 这是一个有点相似的问题In MVVM should the ViewModel or Model implement INotifyPropertyChanged? 但是,唯一的解决方案似乎是将我认为是 UI 逻辑的内容添加到模型中。也许我可以在模型中添加某种委托并从视图模型中挂钩,这将反过来使用 INotifyPropertyChanged... 类似这样的东西?

    public class Task
    {
        public delegate void HandleChange(string propertyName);
        public HandleChange ChangeHandler;

        public int ID 
        { 
            get
            {
                return ID;
            } 
            set
            {
                if(ID != value)
                {
                    ID = value;
                    ChangeHandler("ID");
                }
            }
        }
...

【问题讨论】:

  • 克里斯,您的编辑:这基本上是INotifyPropertyChanged 的实现!您的委托HandleChange 与委托PropertyChangedEventHandler 具有相同的用途,变量ChangeHandlerPropertyChanged 具有相同的用途。唯一的区别是您没有将 ChangeHandler 标记为event(这只是一种保护机制,仅允许订阅和取消订阅,但例如禁止将处理程序设置为 null)。顺便说一句:INotifyPropertyChanged 在程序集中System.dll,命名空间System.ComponentModel;它根本与 WPF 或 UI 无关。

标签: wpf entity-framework mvvm code-first ef-code-first


【解决方案1】:

我知道这是一个旧线程,但我在谷歌上搜索这个主题并偶然发现了这篇 blogs.msdn.com 文章:http://bit.ly/iE3KHI

简而言之,从 EF CodeFirst 的 CTP 4 开始,CodeFirst dbSet 对象有一个新属性 .Local。 .Local 是实现 INotifyPropertyChanged 的​​ ObservableCollection。因此,如果您有一个代码优先的 dbcontext,它公开了一个名为 Tasks 的 DbSet(Of Task),您可以将表单数据上下文设置为 Tasks.Local。

【讨论】:

    【解决方案2】:

    我正在做的是将我的模型类的实例创建为 ViewModel 中的一个属性,然后直接在 Model 上为 Model 属性实现 INotifyPropertyChanged,而在 ViewModel 上仅为 Model 实例实现,如下所示:

    public class Task : INotifyPropertyChanged
    {
        // Implementation of INotifyPropertyChanged
        // Raising the PropertyChanged event in the Setters of all properties
    }
    
    public class TaskViewModel : INotifyPropertyChanged
    {
        private Task _task;
        public Task Task
        {
            get
            {
                return _task;
            }
            set
            {
                if (_task != value)
                {
                    _task = value;
                    RaisePropertyChanged("Task");
                }
            }
        }
    
        // INotifyPropertyChanged implementation
    }
    

    然后在 XAML 中我直接绑定到模型属性,例如:

    <TextBox Text="{Binding Task.Content}" />
    

    (TaskViewModel 将是视图的 DataContext。)

    我这样做主要是为了避免您提到的这种“大量不必要的编码”,而且我找不到缺点。 (我也使用 EF Code-First 使我的模型持久化。)

    【讨论】:

    • @Slauna - 如果你的模型类实现了 INotifyPropertyChanged 那么为什么还要使用 MVVM 呢? MVVM IMO 的主要好处是关注点的分离,以便可以更轻松地在其他项目中使用基本模型对象。我的项目非常大,所以我可以很容易地想象想要在 WCF 服务、ASP.Net 应用程序等中使用基本模型......真的不想要在那里不必要的东西。
    • 在这种特殊情况下它可能是一个有效的解决方案,但通常你没有模型的代码,所以你不能让它实现 INotifyPropertyChanged...
    • @Chris: 1) INotifyPropertyChanged 仅包含一个通用的 .NET 事件,它使对象更改可以从外部观察到。我可以在任何上下文中订阅它,不仅在 WPF/MVVM 中。此事件也可以在其他项目中使用。如果我不需要它,我不订阅。模型属性的变化是模型的一个关注点,所以我不觉得违反关注点分离。 2) 当然,ViewModels 不仅仅是一个 Model 实例,例如与 UI 动作相关联并且确实不属于 Model 的 Commands,...(续)
    • (continue)... 或其他不能直接映射到模型属性的 UI 特定属性。所以,对于这一切,我仍然需要一个 ViewModel。尽管如此,我可以理解你不喜欢这个解决方案,在我决定这样做之前,我也不喜欢它。但是我看不到这种方式的替代方法,或者将所有模型属性复制到 ViewModel 并在 Model 和 ViewModel 属性之间逐个映射。我的模型类现在更胖了(它们也实现了 IDataErrorInfo),但仍然与 WPF 无关。
    • @Slauma - 感谢您的澄清!我可能最终也会走这条路。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-10
    • 1970-01-01
    相关资源
    最近更新 更多