MVVM设计感觉太笨重了,我做错了吗?

Cha*_*rch 7 c# architecture wpf mvvm

我最近开始创建一个WPF应用程序,我只是希望有人可以向我确认我正在构建我的整体系统架构,或者如果我朝某个方向走错了方向纠正我.特别是因为我正在尝试做MVVM,所涉及的层次很多,而且我不确定我是否正常做事.

以下是系统的简要说明:

数据存储在SQL Server数据库中,可通过Linq to SQL访问.假设数据库包含两个表,USERS并且USER_GROUPS.每个表都有一个自动生成的Linq to SQL类,DB_USER以及DB_USER_GROUP.

现在,在应用程序中,我想显示ListBox与每个ListBoxItem用于显示/修改用户的信息,其使用进行含有各种UI元素DataTemplate.

我有一个窗口的视图模型类,它使用Linq to SQL查询(连接两个表)来填充一个ObservableCollection<User>命名UserList,ListBox窗口中的命名为其命名ItemsSource.User是一个实现的类INotifyPropertyChanged,它处理所有格式化/获取/设置数据库数据到WPF控件所需的内容.处理此代码的代码部分类似于:

DBDataContext db = new DBDataContext();

var allUsers = from user in db.USERs
                   .Where(u => u.ENABLED == true)
               from group in db.USER_GROUPs
                   .Where(g => g.GROUPID == u.GROUPID)
                   .DefaultIfEmpty()
               select new { user, group };

foreach (var user in allUsers)
{
    User u = new User(db, user.user, user.group);
    UserList.Add(u);
}
Run Code Online (Sandbox Code Playgroud)

因此,User该类使用a DB_USER,a DB_USER_GROUP和数据库DataContext类的私有属性构造.所有User的公共属性基本上包装相关列,其get方法返回要使用的WPF的值,并set更改列,然后调用SubmitChanges()私有DataContext属性来更新数据库.

这一切都很好,但感觉有点笨拙,所以我只是想知道我是否错过了一些会让它变得更干净的东西.具体来说,在每个元素中存储DataContext UserList似乎很奇怪,但我不确定在UI中更改数据时能够更新数据库的更好方法.

任何反馈都表示赞赏,如果有任何不清楚的地方,请告诉我,我不确定我解释得有多好.

Jon*_*Jon 6

首先,让我们为你在这里做的事情贴上一些标签:DB_USER是你的模型,User是你的ViewModel(我更喜欢UserViewModel后者,以便更清楚发生了什么).

显而易见的一件事是,您的ViewModel具有适合您的模型的功能并不合适,即它DataContext不属于当前所在的位置.这是一条信息,应该在您的模型中,或者在某些DataStore/ DataService(选择)类中封装.然后,当保存任何更改时,您的ViewModel将负责告诉DataStore"这里是此模型的更新快照,请为我保存"(这很可能会通过a暴露给用户界面ICommand).这感觉更清晰,并强调了ViewModel是一个层,可以根据您选择的UI调整模型的实际情况.

除了上述内容之外,您所描述的内容并不是我认为需要"纠正"的内容.但是,我可以就你没有详细说明的事情提出一些建议.

通过ViewModel公开模型中的数据总是可以通过多种方式实现.在考虑采取何种方法时,您应该考虑同一模型同时通过不同视图公开的可能性.在这种情况下,恕我直言,首选方法是为每个View设置一个单独的ViewModel(视图可能是不同类型的,因此它们可能与ViewModel适配器有不同的期望,因此也指向多种类型的ViewModel),所以你需要使用一种模式,允许更改从"实时"从一个ViewModel传递到任何其他ViewModel.

实现此目的的一种方法是让您的模型INotifyPropertyChanged自己实现并将每个ViewModel挂钩到其模型中以进行通知,因此当发生更改时,ViewModel A会将更改推送到模型,模型会通知ViewModel B.

不过个人而言,我不喜欢使用基本上只满足UI需求的代码来污染我的模型,因此需要另一种方法.这将使DataService我上面提到的暴露功能(方法和事件)ViewModel A可以告诉服务"嘿,模型I包装已经有了一些变化"; 请注意,这与"我希望您保留此模型的当前快照"不同.ViewModel B已经连接到一个合适的"ModelChanged"事件,因此它会得到通知并从服务中提取更新的信息.这具有额外的好处,即如果服务在任何时候检测到后备数据存储库已被当前进程外部的源更新,则有一个现成的机制来广播"调用所有ViewModels:模型X已更新,任何有兴趣的人士请跟我谈谈学习细节"的消息.

最重要的是,请记住,没有"真正的MVVM风格",并且有无数种可能的方法.要采取哪一个不仅取决于事实和YAGNI/HyperEngineering规模上滑块的当前位置,还取决于我敢说的你的品味.