gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 20:03:28 26 4
gpt4 key购买 nike

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

这是对系统的简单描述:

数据存储在 SQL Server 数据库中,可通过 Linq to SQL 访问。假设数据库包含两个表,USERSUSER_GROUPS .每个表都有一个自动生成的 Linq to SQL 类,DB_USERDB_USER_GROUP .

现在在应用程序中,我想显示一个 ListBox每个 ListBoxItem包含用于显示/修改用户信息的各种 UI 元素,这是使用 DataTemplate 完成的.

我有一个窗口的 View 模型类,它使用 Linq to SQL 查询(连接两个表)来填充 ObservableCollection<User>名为 UserList ,其中 ListBox在窗口中已绑定(bind)为其 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);
}

所以 User类是用 DB_USER 的私有(private)属性构造的, 一个 DB_USER_GROUP和数据库 DataContext 类。所有的 User的公共(public)属性基本上用它们的 get 包装相关列返回 WPF 要使用的值的方法,以及 set更改列然后调用 SubmitChanges()在私有(private) DataContext 属性上更新数据库。

一切正常,但感觉有点笨拙,所以我想知道我是否遗漏了一些可以使它更干净的东西。具体来说,在 UserList 的每个元素中存储一个 DataContext。看起来很奇怪,但我不确定是否有更好的方法能够在 UI 中更改数据时更新数据库。

欢迎任何反馈,如果有任何不清楚的地方,请告诉我,我不确定我解释得如何。

最佳答案

开始,让我们为您在这里所做的事情贴上一些标签:DB_USER 是您的模型,User 是您的 ViewModel(我更喜欢 UserViewModel 对于后者只是为了更清楚发生了什么)。

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

除上述内容外,我认为您描述的内容没有任何需要“更正”的地方。但是,我可以就您未详细说明的内容提供一些建议。

通过 ViewModel 从 Model 公开数据始终可以通过多种方式实现。在考虑采用何种方法时,您应该考虑到同一模型同时通过不同 View 公开的可能性。在这种情况下,恕我直言,首选方法是为每个 View 创建一个单独的 ViewModel( View 可能属于不同类型,因此它们可能对 ViewModel 适配器有不同的期望,因此也指向多种类型的 ViewModel),因此您将需要使用一种模式,允许“实时”将更改从一个 ViewModel 传达给任何其他 ViewModel。

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

但是我个人不喜欢用本质上只满足 UI 需求的代码来污染我的模型,因此需要另一种方法。这将使我上面提到的 DataService 公开功能(方法和事件),ViewModel A 可以通过这些功能告诉服务“嘿,我包装的模型发生了一些变化”;请注意,这与“我希望您保留此模型的当前快照”不同。 ViewModel B 已经连接到合适的“ModelChanged”事件,因此它会收到通知并从服务中提取更新的信息。这有一个额外的好处,如果服务在任何时候检测到支持数据存储库已被当前进程外部的源更新,则有一个现成的机制来广播“调用所有 ViewModels:Model X 已更新,任何有意者请与我交流了解详情”留言。

最重要的是,请始终记住,没有“一种真正的 MVVM 风格”,并且有无数种可能的方法。选择哪一个不仅取决于确凿的事实和 slider 在 YAGNI/HyperEngineering 量表上的当前位置,而且我敢说,还取决于您的品味

关于c# - MVVM 设计感觉太笨重,我做错了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8422999/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com