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# MVVM设计感觉太笨拙了,我做错了吗?_C#_Wpf_Architecture_Mvvm - Fatal编程技术网

C# MVVM设计感觉太笨拙了,我做错了吗?

C# MVVM设计感觉太笨拙了,我做错了吗?,c#,wpf,architecture,mvvm,C#,Wpf,Architecture,Mvvm,我最近开始创建一个WPF应用程序,我只是希望有人能向我确认我正在正确地构建我的整个系统架构,或者如果我在某个地方走错了方向,就纠正我。特别是因为我正在尝试做MVVM,涉及到很多层,我不确定我做的事情是否正确 以下是系统的简化说明: 数据存储在SQL Server数据库中,该数据库通过Linq to SQL进行访问。假设数据库包含两个表,USERS和USER\u GROUPS。每个表都有一个自动生成的Linq to SQL类、DB\u USER和DB\u USER\u组 现在在应用程序中,我想显示

我最近开始创建一个WPF应用程序,我只是希望有人能向我确认我正在正确地构建我的整个系统架构,或者如果我在某个地方走错了方向,就纠正我。特别是因为我正在尝试做MVVM,涉及到很多层,我不确定我做的事情是否正确

以下是系统的简化说明:

数据存储在SQL Server数据库中,该数据库通过Linq to SQL进行访问。假设数据库包含两个表,
USERS
USER\u GROUPS
。每个表都有一个自动生成的Linq to SQL类、
DB\u USER
DB\u USER\u组

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

我有一个用于窗口的视图模型类,它使用Linq到SQL查询(连接两个表)来填充名为
UserList
observeCollection
,窗口中的
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);
}
因此,
User
类是用
DB\u用户
、DB\u用户组和数据库DataContext类的私有属性构建的。
用户
的所有公共属性基本上包装了相关列,它们的
get
方法返回WPF要使用的值,并
set
更改列,然后在私有DataContext属性上调用
SubmitChanges()
,以更新数据库

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


任何反馈都非常感谢,如果有什么不清楚的地方,请告诉我,我不确定我解释得有多好。

通常,我会尽可能地保持我的模型(POCO)。我的viewmodel具有查询数据库和设置绑定到UI的属性的繁重逻辑。在该布局中,viewmodel有一个DataContext实例,不需要在模型内部传递它。

首先,让我们在这里做一些标记:
DB\u USER
是您的模型,
USER
是您的viewmodel(对于后者,我更喜欢
UserViewModel
,以便更清楚地了解发生了什么)

一件很明显的事情是,ViewModel没有适合您的模型的功能,也就是说,
DataContext
不属于它当前所在的位置。这是一段信息,应该在您的模型中,或者封装在一些
数据存储中Service
(选择)类。然后,当需要保存任何更改时,您的ViewModel将负责告诉
数据存储
“这是此模型的更新快照,请为我保存”(这很可能通过
ICommand
向UI公开)。这让人感觉更清晰,并强调了您的ViewModel是一个根据您选择的UI调整模型现实的层

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

通过ViewModel公开模型中的数据总是可以通过多种方式实现的。在考虑采取何种方法时,应考虑同一模型同时通过不同视图公开的可能性。在这种情况下,首选方法是为每个模型提供单独的ViewModel视图(视图可能具有不同的类型,因此它们可能与ViewModel适配器有不同的期望值,因此也指向多种类型的ViewModels),因此您需要使用一种模式,允许“实时”将更改从一个ViewModel传递给任何其他ViewModel

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

然而,就我个人而言,我不喜欢用本质上只满足UI需求的代码污染我的模型,因此需要另一种方法。那就是让我上面提到的
DataService
公开ViewModelA可以告诉服务的功能(方法和事件)“嘿,我正在包装的模型有一些更改”;请注意,这与“我希望您保存此模型的当前快照”不同。ViewModel B已连接到一个合适的“ModelChanged”“事件,因此它会收到通知并从服务中提取更新的信息。这还有一个额外的好处,即如果服务在任何时候检测到备份数据存储库已由当前进程外部的源更新,则有一个现成的机制来广播“调用所有ViewModels:Model X已更新,任何感兴趣的人请与我联系了解详细信息”消息

最重要的是,请始终记住,没有“一种真正的MVVM风格”,并且有无数种可能的方法。采取哪种方法并不取决于