c# - MVVM,对ViewModelLocator和DataTemplate感到困惑,导致ViewFirst vs ViewModel First

标签 c# wpf mvvm mvvm-light

我使用 MVVMLight,它带有一个 ViewModelLocator。

我最初的项目提出了以下问题。我有一个在启动应用程序时呈现的 MainView。根据单击的按钮,它会通过 MainView 内的 ContentControl 呈现 View1 或 View2(每个都是用户控件)。

我在 MainViewModel 中找到了正确的 View 模型。但我发现我还需要一个 DataTemplate,以便 View1 和 View2 中的用户控件能够在 MainView 中正确呈现,否则它只会显示基于文本的类名称。

我对以下内容感到困惑:

a) 我是否需要 View 模型定位器和 DataTemplate 来完成上述任务?我刚刚跳入 WPF,但我认为我读到其中之一是必需的,而不是两者都需要。或者更具体地说:为什么我的 View 中有 DataContext="{Binding LiveDataViewModel, Source={StaticResource Locator}}"> (它解析到其自己的 View 模型的绑定(bind))但仍然需要 DataTemplate ?

b)这是 View 模型优先方法还是 View 优先方法?

c) 我尝试了一个代码隐藏解决方案,它实际上花了我 4 行代码来完成同样的事情,这让我花了很多类、弯路、eventToCommand 和转换器 [因为触发 View 选择的控件只会引发事件不是命令]、数据模板、 View 模型定位器、不同的 View 模型……这看起来像是在没有任何优势的情况下付出了巨大的成本。在我看来,将其放入代码后面似乎完全没问题,因为它是纯 UI 内容(选择 View 并绑定(bind)到内容控件,完成)。我在这里错过了什么吗?通过代码隐藏我会放弃什么?

我是 WPF 和 MVVM 的新手,现在我非常沮丧,因为感觉就像我在围绕一个看似微不足道的问题兜圈子。

最佳答案

如果这个答案听起来很基础,我很抱歉,但听起来您可能仍在学习 WPF 并误解了一些关键的事情。

首先,WPF 应用程序有两层:

  • 由您在屏幕上看到的渲染对象组成的 UI 层
  • 以及位于 UI 后面的数据层,称为 DataContext

当您进行绑定(bind)时,您将从数据层提取数据并将其放置在 UI 层中。

ViewModelLocator 影响数据层。它用于查找适当的数据对象以放置在 UI 对象后面。

现在,如果数据对象直接插入到 UI 层中,例如任何具有直接绑定(bind)到其数据层的 .Content.ItemsSource 属性的内容, WPF 呈现数据对象的默认方式是使用显示对象的 .ToString()TextBlock

您可以覆盖它并告诉 WPF 如何使用 DataTemplate 绘制任何类型的对象。您可以告诉控件使用特定模板进行呈现,也可以告诉 WPF 使用特定的 DataTemplate 自动呈现 X 类型的 UI 层中的任何对象。

所以回答你的问题

a) Do I need both, a view model locator and a DataTemplate to accomplish the above? Or more specific: Why do I have DataContext="{Binding LiveDataViewModel, Source={StaticResource Locator}}"> in my View but still need a DataTemplate?

这是两个独立的项目。 ViewModelLocator 定位 UI 对象后面的数据项,DataTemplate 告诉 WPF 如何绘制该项目。

您的绑定(bind)表示“将数据层 (DataContext) 绑定(bind)到 Locator.LiveDataViewModel”,我最好的猜测是您的 XAML 中的某些内容绑定(bind)了 ItemsSource Content 直接到数据层,使用像 Content="{Binding }"

这样的 XAML

b) Is this a view model first approach or a view first approach?

我认为任何时候使用 ViewModelLocator 都是 View 优先的方法,因为 View 负责从定位器获取其数据项。在 View 调用数据之前,数据并不存在。

就我个人而言,我从不使用ViewModelLocator,因为我不喜欢它的限制,并且更喜欢模型优先的方法,但这并不意味着如果您愿意就不能使用它.

c) I tried a code behind solution and it literally took me 4 lines of code to accomplish the exact same thing that took me many classes, detours, eventToCommand & converters [because the control that triggers the choice of view only raises events not commands], data templates, view model locators, different view models...this looks like a huge cost to pay for no advantage whatsoever. Putting this into code behind seems to me perfectly fine because it is pure UI content (choose view and bind to content control, done). Am I missing something here? What would I give up via code behind?

我不知道你的代码是什么样的,但是听起来其中有很多不必要的代码。 MVVM 模式背后的想法是让所有应用程序逻辑驻留在类中,所有用户界面逻辑驻留在 UI 控件中。 WPF 由于其绑定(bind)系统而非常适合这种设计。

这使得将备用用户界面连接到您的应用程序变得很容易,最常见的是测试脚本。它还具有使 UI 与业务逻辑完全分离的优点,这在与专门的 UI 团队合作时提供了巨大的帮助。

我个人对每个 WPF 应用程序都使用 MVVM,即使是非常简单的应用程序。我可能会在简单的应用程序中稍微模糊一些规则,但是当 MVVM 选项存在时,我永远无法回到构建应用程序的旧 WinForms 风格。

如果您有兴趣,我为 WPF 初学者编写了几篇博客文章,如果您刚开始接触这些文章,可能会对您有用:

希望这有帮助,祝你好运:)

关于c# - MVVM,对ViewModelLocator和DataTemplate感到困惑,导致ViewFirst vs ViewModel First,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27625181/

相关文章:

asp.net-mvc - MVC 和 MVVM 有什么区别和相似之处?

c# - ASP.NET Core 3.1 MVC 如何让用户在注册时选择自己的角色?

c# - 当一个属性被设置后,即使它没有改变,它的值也应该更新吗?

c# - 是否可以继承 XAML?

c# - 等价于 C# 中的 yield

c# - 在设计 View 上更改 tabcontrol 的选项卡项

c# - 如何在 WPF 中绑定(bind)多个嵌套属性

c# - 如何根据属性隐藏 wpf 数据网格列

c# - 按钮内容变化

c# - WPF MVVM - 从 ViewModel 访问 View 中 DataGrid 的 DependencyProperty