MVVM查看对ViewModel的引用

时间:2010-03-29 16:30:37

标签: mvvm

我在WPF应用程序中使用MVVM。我对两者都很陌生。让我说明我不是MVVM模式中最纯粹的,我试图尽可能多地使用尽可能多的最佳实践,但我正在努力做出我认为合理的妥协,使其在我们的环境中运行。例如,我不想在我的View代码隐藏中实现0%的代码。

我对最佳做法有几个问题。

1)我理解我不希望我的VM了解附加的View,但是View对其VM的引用是否合理?

2)如果视图中的控件打开另一个视图(例如对话框),我应该在视图中处理吗?在VM中处理它似乎是错误的,因为VM知道特定的View。

5 个答案:

答案 0 :(得分:13)

1)View绝对通过DataContext引用了ViewModel。并且您可以在视图中投射DataContext:

public class ShellView : Window 
{
   …
   public ShellViewModel { get { return DataContext as ShellViewModel; } }

这不违反Model-View-ViewModel模式。

2)你是对的。 ViewModel不应该打开另一个View。更好的方法是使用控制器。他们负责应用程序的工作流程。

如果您对更详细的信息感兴趣,可以查看 WPF Application Framework (WAF)

答案 1 :(得分:3)

1)以下是View的“了解”ViewModel的两个简单实践。 View知道ViewModel(用于数据绑定)是合理的 - 但在您的情况下可能不需要它。看看这些方法中的任何一种是否有助于解决您的问还有其他方法,但这些方法应该足够简单:

public View(ViewModel vm)
{
     View.DataContext = vm;
}

public Bootstrapper(View v, ViewModel vm)
{
     v.DataContext = vm;
     //or, if you want it to have no parameters
     View v = new View();
     ViewModel vm = new ViewModel();
     v.DataContext = vm;
}

如果你有一个服务定位工具,第一个选项也不错,但有一种MVVM不喜欢View的Code-Behind中的任何代码。第二种选择也不错,应该足够简单,适合你的任务。

2。)这个问题在MVVM设计中可能有点棘手。如果我们谈论的是一般的Win32 MessageBox,我会经常将该逻辑分成另一个对象并将其放入VM中。这种方式往往更加清晰。 (例如,我在ListBox中选择了一个项目,我已经将删除ICommand附加到该操作,并且在我的ViewModel中执行此ICommand时,我将戳我的MessageBoxObject以询问用户是否“想要真正删除”这个项目)。更高级的“Dialogs”将为这些ViewModel使用额外的ViewModel和DataTemplates。我更喜欢Mediator方法。

答案 2 :(得分:2)

1)。视图需要在某个级别引用视图模型,因为视图模型将充当视图的datacontext。

2)处理此问题的一种方法是使用一个表示对话框的通用视图模型,该视图由主视图模型(用作视图datacontext的那个)拥有。

您可以使用命令来创建对话框视图模型的新实例,该实例将在您的资源中定义相应的数据窗口。此模板将设置为绑定到dialogviewmodel类型。

答案 3 :(得分:2)

很晚,但我觉得这很难得到很多不同的观点。


  

我知道我不希望我的VM了解附加的View,但是   View是否合理地引用其VM?

正如已经回答的那样,正确的View-ViewModel安排涉及将ViewModel指定为View的DataContext属性。这允许DataBindings从声明性XAML“自动”建立,或通过后面的代码进行微调。

有时候,你会想要在你的代码中写下这样的东西:

var dc = DataContext as CleverViewModel;
CleverViewModel.CleverProperty.Add(someValue); // just a simple example

我认为实现这类事情的正确方法不是转换DataContext,而是:

  1. 在View中有一些专用控件,例如ItemsControl及其ItemsSource双向数据绑定到viewmodel中的某些属性

    <ItemsSource x:Name="cleverControl" Visibility="Collapsed" ItemsSource="{Binding CleverProperty, Mode=TwoWay}"/>

  2. 在后面的代码中转换绑定属性而不是整个ViewModel:

    var collection = (ObservableCollection<double>)cleverControl.ItemsSource; collection.Add(someValue);

  3. 请注意重要的区别:此示例中的第二种方法不要求View知道ViewModel类型,它只需要一个名为CleverProperty的{​​{1}}类型的属性。这允许我有多态甚至鸭型的ViewModels。


      

    如果视图中的控件打开另一个视图(例如对话框),我应该   在View中处理这个?从那以后在VM中处理它似乎是错误的   然后,VM了解特定的视图。

    这不应该发生在严格的MVVM中,并且使用DataTemplates也不难避免。 DataTemplates将给定类型的DataContext映射到给定类型的视图,因此只要ContentControl的datacontext发生更改,其显示也会发生变化,前提是您拥有该类型的DataTemplate:

    1. 视图中的控件可以向ViewModel发送命令,而ViewModel又会更新一些自己的属性,这些属性将被视图反映出来。

      < / LI>
    2. 在ViewModel知识之外,View可以包含另一个View。在这种情况下,后面的代码可以操作包含视图的datacontext。

    3. 还有更多细微之处,但我一直在使用这种方法,效果很好。希望这有助于某人。

答案 4 :(得分:1)

Build Your Own MVVM Framework

我发现Rob Eisenberg提出的方法非常有趣。

关键点:

  1. 约定优于配置
  2. ViewModel首先
  3. 这与ASP.NET MVC哲学非常相似。

    我强烈建议观看视频。