【问题标题】:MVVM - How do I Bind the View Model to the ViewMVVM - 如何将视图模型绑定到视图
【发布时间】:2011-04-28 15:39:49
【问题描述】:

提前感谢您的指导。我是 MVVM 的新手,我一直在通过文章学习。我想我已经走得很远了,但有一件事似乎让我无法理解。我如何(不使用后面代码中的代码)自动绑定到我想要的视图?据我了解,如果做得正确,这就是模式应该如何工作的。我可以使用主窗口 xaml 中的代码来完成这一切,我什至已经正确创建了一个资源字典(因为我可以在即时窗口中访问它。)我只是无法进入“自动化”的下一步。 '这可能是我的设计,因为我是这种模式的新手,我完全可以接受我做错了这一切的可能性。这就是我所拥有的......

我有一个主窗口。这是一个有 3 行的网格。顶行是一个菜单。最下面一行是状态栏。中间是一个堆栈面板,内容根据菜单选择动态加载。

我有 2 个视图用于填充此堆栈面板。一个只有一个样式化的文本框(Help & About)。另一个本身就是一个复合视图:一个搜索面板、一个结果网格和一个详细面板都加载到一个停靠管理器框架中。

在后面的主窗口代码中,当用户单击菜单选项时,我清除堆栈面板的子项,实例化视图模型,实例化将视图模型传递给其中的视图,然后将新视图添加到子项中的堆栈。这很好用,但我认为它与模式不一致。

正如我提到的,我有资源字典,但我不知道如何将它与堆栈面板相关联。我假设我必须使用绑定,但我不知道如何绑定到资源字典和/或如何告诉它更改命令视图。

我读过的文章已将所有可用的视图模型添加到视图模型中的只读列表中,该列表基本上充当主寡妇和所需的实际视图模型之间的通道。这看起来不错,但我不明白为什么需要资源字典。此外,这些示例是向导实现,在这种情况下,这似乎是一个不错的方法,但我无法想象对于具有 100 个视图模型的应用程序这样做。

再次为我的无知感到抱歉,但我希望有人能指出我正确的方向。正如我所说,我已经阅读了大量文章(Josh Smith、Dave Hill 等),但我仍然没有建立联系,所以我希望得到一些具体的指导。 (我确实有 WPF Unleashed,但我希望在那之前取得一些进展。)

谁能帮忙?

【问题讨论】:

  • 没有时间完全回答这个问题,但也许这会让你开始。在资源字典中,您可以为 ViewModel 类型设置默认视图。然后,当您将 ViewModel 的一个实例作为某种 ItemPresenter 的 Content 时,它将使用该默认实例化并神奇地为 ViewModel 显示正确的视图。然后你所要做的就是创建一个带有区域的窗口(或一些类似的,查找它们)并使用区域管理器填充该区域。在这里查看问题stackoverflow.com/questions/5767759/…
  • 我想我明白了,但你能确认一下吗?资源字典只是关联特定视图和视图模型的捷径。但尽管如此,无论以何种方式选择执行此操作,您仍然需要在某处显示“触发此事件时,清除现有内容并添加此新内容”的代码。是这样吗?似乎有更好的方法来处理内容的切换,例如您的区域经理。我认为我在阅读“......没有代码背后......”时感到困惑,我认为这意味着内容切换代码不存在。

标签: wpf mvvm binding view viewmodel


【解决方案1】:

有一些方法可以绑定你的视图模型。

1.在 XAML 中创建静态资源。

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
  <Window.Resources>
    <local:MainViewModel x:Key="MainVM" />
  </Window.Resources>
  <Grid DataContext="{StaticResource MainVM}">

  </Grid>
</Window>

2。在 View 的构造函数中绑定

我知道您提到不使用代码,但这也是一种选择。只要您不在后面的代码中编写任何逻辑,就可以了。

public MainWindow()
{
  InitializeComponent();
  this.DataContext = new MainViewModel(); 
}

3.使用 ViewModelLocator 绑定

您可能想要创建一个视图模型定位器类,该类负责为您的视图提供所需的视图模型。

这是一个视图模型定位器类的简单示例。 viewmodel 定位器类公开了一些 viewmodel 属性。然后稍后我们会将这些属性绑定到视图的数据上下文。

 public class ViewModelLocator
  {
    public ViewModelLocator()
    {
      this.MainVM = new MainViewModel();
      this.AnotherVM = new AnotherViewModel();
    }
    public MainViewModel MainVM { get; set; }
    public AnotherViewModel AnotherVM { get; set; }
  }

然后您可以在 App.xaml 中创建视图模型定位器的静态资源,以使其可用于应用程序中的所有视图。

<Application x:Class="WpfApplication2.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplication2"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
      <local:ViewModelLocator x:Key="Locator" />         
    </Application.Resources>
</Application>

然后您可以将视图的数据上下文绑定到视图模型定位器的属性。

该示例告诉我们,如果作为 MainViewModel 实例的 viewmodel 定位器绑定到 Window 的数据上下文,则您正在绑定 MainVM 属性。

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication2"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"
        DataContext="{Binding MainVM, Source={StaticResource Locator}}">

【讨论】:

    【解决方案2】:

    我没有使用过 WPF,但我使用过 Silverlight,我相信它应该几乎相同。

    当我创建我的视图时,我在视图中实例化了所需的 ViewModel。我使用 MEF 进行依赖注入并以这种方式创建所需的 VM,您可能不想走这条路,但它可以给您一个想法。

    例如视图模型:

    [Export] // This attribute tells MEF to export an instance of this class
    public class MyViewModel
    { ... }
    

    查看

    [Import] // MEF will look for any exported objects of type MyViewModel
    public MyViewModel ViewModel
    {
      get { return this.DataContext as MyViewModel; }
      set { this.DataContext = value; }
    }
    

    这种方式无需实例化您的 VM 和您的 V,只需创建您的 V 并让其关心实例化 VM 并设置它自己的 DataContext。

    【讨论】:

    • 对。我做了类似的事情。谢谢,但我的问题更像是 J Trana 上面评论的内容。基本上,如何在没有代码的情况下切换内容?而且我认为,根据我所读到的,你没有。
    • 有没有办法在没有 MEF 的情况下进行导入/导出操作?
    • @JelleCapenberghs 实际的导入/导出属性是特定于 MEF 的,但您可以使用另一个依赖注入框架,或者编写自己的导入/导出属性来找到合适的类型来实例化
    猜你喜欢
    • 1970-01-01
    • 2011-08-25
    • 2011-10-07
    • 1970-01-01
    • 2012-07-31
    • 1970-01-01
    • 2018-10-25
    • 2011-01-18
    相关资源
    最近更新 更多