MVVM 在视图中绑定正交方面,例如应用程序设置
我有一个正在使用 WPF\Prism\MVVM 开发的应用程序。一切都很顺利,我已经有了一些令人满意的 MVVM 实现。然而,在我的一些观点中,我希望能够绑定应用程序设置,例如,当用户重新加载应用程序时,应在用户上次使用该应用程序的状态下选中自动滚动网格的复选框。
我的视图需要绑定到保持“自动滚动”设置状态的东西。我可以将其放在视图模型上,但应用程序设置与视图模型的用途正交。 “自动滚动”设置控制视图的一个方面。此设置仅是一个示例。它们将会有相当多,并且用属性来表示我的视图模型来表示应用程序设置(这样我可以绑定它们)感觉绝对令人讨厌。
每个视图一个视图模型似乎是惯例......
这里最好的\通常的做法是什么?
- 使用应用程序设置来分散我的视图模型?
- 每个视图有多个视图模型,以便设置可以以自己的方式表示?
- 拆分视图以便控件可以绑定到 ApplicationSettingsViewModel? = 浏览量太多?
- 还有别的事吗?
编辑 1
为了添加更多上下文,我正在开发一个带有动态选项卡式界面的 UI。每个选项卡将托管一个小部件,并且有多种小部件。每个小部件都是各个视图的 Prism 组合。一些视图在小部件中很常见,例如文件选择器视图。虽然每个小部件都由多个视图组成,但从概念上讲,小部件具有一组用户设置,例如最后选择的文件、启用自动滚动等。当应用程序再次启动时,需要保留并检索\应用这些设置,并且小部件视图被重新创建。
我的问题集中在这样一个事实:从概念上讲,小部件具有一组用户设置,这与小部件由许多视图组成的事实成直角。小部件中的每个视图都有自己的视图模型(工作得很好且符合逻辑),但是如果我坚持每个视图一个视图模型,我将不得不使用用户设置支持的属性来分散每个视图模型(这样我就可以进行数据绑定)。
如果我必须使用用户设置属性来分散每个视图模型,那么每个视图一个视图模型在这里听起来并不合适。
I have an application which I am developing using WPF\Prism\MVVM. All is going well and I have some pleasing MVVM implementations. However, in some of my views I would like to be able to bind application settings e.g. when a user reloads an application, the checkbox for auto-scrolling a grid should be checked in the state it was last time the user used the application.
My view needs to bind to something that holds the "auto-scroll" setting state. I could put this on the view-model, but applications settings are orthogonal to the purpose of the view-model. The "auto-scroll" setting is controlling an aspect of the view. This setting is just an example. There will be quite a number of them and splattering my view-models with properties to represent application settings (so I can bind them) feels decidedly yucky.
One view-model per view seems to be de rigeuer...
What is best\usual practice here?
- Splatter my view-models with application settings?
- Have multiple view-models per view so settings can be represented in their own right?
- Split views so that controls can bind to an ApplicationSettingsViewModel? = too many views?
- Something else?
Edit 1
To add a little more context, I am developing a UI with a dynamic tabbed interface. Each tab will host a single widget and there are a variety of widgets. Each widget is a Prism composition of individual views. Some views are common amongst widgets e.g. a file picker view. Whilst each widget is composed of several views, conceptually a widget has a single set of user settings e.g. last file selected, auto-scroll enabled, etc. These need to be persisted and retrieved\applied when the application starts again, and the widget views are re-created.
My question is focused on the fact that conceptually a widget has a single set of user settings which is at right-angles to the fact that a widget consists of many views. Each view in the widget has it's own view-model (which works nicely and logically) but if I stick to a one view-model per view, I would have to splatter each view-model with user setting backed properties (so I can databind).
A single view-model per view doesn't sound right here if I have to splatter each view-model with user setting properties.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这里的基本问题是使用 Prism 组合子视图来制作小部件 - 子视图太细粒度。
小部件是子视图(用户控件)的集合,它们一起工作以形成单个视图,例如组合“文件选择器”和“网格列表”。应使用简单的 Xaml 来组合子视图以形成复合视图。您仍然可以获得各个用户控件的可重用性,但小部件的组成在设计时是固定的。
现在我们有了一个视图:WidgetView(由用户控件组成),我们可以将该视图绑定到单个视图模型:WidgetViewModel。然后通过组合多个视图模型来处理小部件视图的设置。只需在 WidgetViewModel 上放置一个公开 WidgetSettingsViewModel 的属性即可。用户控件绑定 WidgetViewModel 以与底层模型交互,但绑定到 WidgetSettingsViewModel 以进行小部件设置。
通过这种方式,我们可以将主视图模型和设置视图模型绑定到小部件。
The basic problem here is using Prism to compose sub-views to make the widget - sub-views are too fine-grained.
A widget is a collection of sub-views (user controls) that work together to form a single view e.g. combining a "file picker" and a "grid list". The sub-views should be composed using straightforward Xaml to make a composite view. You still get the re-usability of the individual user controls, but the composition of the widget is fixed at design time.
Now that we have a single view: WidgetView (made of user controls), we can bind that view to a single viewmodel: WidgetViewModel. Handling the settings for the widget view is then handled by composing multiple viewmodels. Simply place a property on WidgetViewModel that exposes a WidgetSettingsViewModel. User controls bind WidgetViewModel for interacting with the underlying model, but bind to WidgetSettingsViewModel for widget settings.
In this way we can have a main viewmodel and a settings viewmodel bound to a widget.
我发现直接绑定到应用程序设置最简单,如下所示:
假设您正在使用 System.Configuration 的应用程序设置功能,如 Visual Studio 的“.settings”文件公开的那样。如果您使用其他机制来保存设置,则此技术仍然有效:只需在静态对象上公开您的用户和应用程序设置并绑定到它即可。
如果您有一个包含大量应用程序设置的“选项”对话框,则可以通过使用“设置”对象作为 DataContext 来简化操作:
请注意,如果您这样做,您可以在应用程序退出时免费保存您的设置,并且任何更改都可以保存在应用程序中。设置将立即反映在您的用户界面中。
我还发现将设置绑定到对象的非 UI 属性很有用,这样当应用程序设置更改时,对象将接收 PropertyChangedCallback 事件,从而使更新变得简单,并避免因大量不必要的事件注册而使我的代码变得混乱。
I've found it easiest to bind directly to the application settings, like this:
This is assuming you are using System.Configuration's application settings feature, as exposed by Visual Studio's ".settings" files. If you're using some other mechanism to save your settings, this technique will still work: Simply expose your user and application settings on a static object and bind to it.
If you have an Options dialog that has lots of application settings, you can simplify things by using the Settings object as your DataContext:
Note that if you do it this way you get your settings saved for free when the application exits, and any change in settings will be instantly reflected in your UI.
I've also found it useful to bind settings to non-UI properties of my objects so the objects will receive PropertyChangedCallback events when application settings change, making their update simple and avoiding cluttering my code with lots of unnecessary event registrations.
啊,你的编辑足以澄清事情,足以保证一个新的答案。就是这样:
视图模型被称为“视图模型”的全部原因是因为它确实是一个模型。是的,它通常不会保存到磁盘(尽管可以),但它具有模型的所有其他方面:它存储用户数据,它从视图绑定,它没有对视图的引用,等等 在您的情况下,
您有一组想要与每个 {user, widget} 组合关联的设置。该设置集合需要保留并在每个视图中可用。从概念上讲,这是一个单独的模型对象:它不是小部件,不是用户,也不是特定于视图的。无论您称其为“视图模型”还是简称为“模型”,主要是术语问题。无论您想对它进行分类,我们都可以将该对象本身称为
UserWidgetSettings
。您将在某个地方有一个后备存储,您将在其中保存 UserWidgetSettings 对象。这可能位于本地文件、注册表中或存储用户和小部件对象的同一数据库中。为了便于讨论,假设您将它们与 User 和 Widget 对象分开存储,并有一个类来保存它们:
现在,视图使用的 ViewModel 只需要一个属性来访问设置:
在您的视图中,您可以使用设置如下:
控制它的复选框如下所示:
附注:我发现平均只有大约 20% 的视图实际上需要自己的视图模型。其余的可以使用模型本身公开的通用属性。如果您发现自己为每个视图创建了单独的视图模型,则可能会出现问题。您可能想看一下您在视图模型中所做的某些事情是否与在模型本身中做的事情一样或更有意义。底线:精心设计的模型对象可以显着减少 WPF 应用程序中的代码量。
Ah, your edit clarifies things enough to warrant a new answer. Here it is:
The whole reason a view model is called a "view model" is because it really is a model. Yes, it ususally doesn't get saved to disk (though it could), but it has all of the other aspects of a model: It stores user data, it is bound from a view, it has no references to the view, etc.
In your case you have a collection of settings that you want to associate with each {user, widget} combination. This collection of settings needs to be persisted and available in each of your views. Conceptually this is a separate model object: It is not a widget, it is not a user, and it is not view-specific. Whether you call it a "view model" or simply a "model" is primarily a matter of terminology. However you want to classify it, let's call the object itself
UserWidgetSettings
.Somewhere you will have a backing store to which you will persist UserWidgetSettings objects. This may be in a local file, in the registry, or in the same database where your User and Widget objects are stored. For sake of discussion let's say you have them stored separately from the User and Widget objects, and have a class that persists them:
Now your ViewModels used by the views simply need a property to access the settings:
In your view, you can use the settings thusly:
And your checkbox to control it looks like this:
A side note: I've found that on average only about 20% of my views actually need their own view model. The rest can use common properties exposed by the model itself. If you find yourself creating a separate view model for every single view, something may be wrong. You may want to take a look and see if there are some things you're doing in the view model that would make as much or more sense to do in the model itself. Bottom line: Well-designed model objects can dramatically cut down on the amount of code in a WPF application.