MVVM - 如何将视图模型绑定到视图

发布于 2024-11-03 14:26:54 字数 899 浏览 0 评论 0原文

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

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

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

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

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

我读过一些文章,这些文章将所有可用的视图模型添加到视图模型中的只读列表中,该视图模型本质上充当主窗口和所需的实际视图模型之间的桥梁。这看起来没问题,但我不明白为什么需要资源字典。此外,这些示例是向导实现,在这种情况下,这似乎是一个很好的方法,但我无法想象对具有 100 个视图模型的应用程序执行此操作。

再次为我的无知感到抱歉,但我希望有人能指出我正确的方向。正如我所说,我读过大量文章(乔什·史密斯、戴夫·希尔等),但我仍然没有建立联系,所以我希望得到一些具体的指导。 (我确实正在开发 WPF Unleashed,但我希望在此之前取得一些进展。)

有人可以帮忙吗?

and thanks in advance for the guidance. I'm new to MVVM, and I've been learning via articles. I think I've gotten pretty far, but there's one thing that seems to escape me. How do I (not using code in the code behind) automatically bind to the view I want? As I understand it, if done correctly, this is how the pattern should work. I can make this all happen using code behind in the main window xaml, and I have even created a resource dictionary correctly (as I can access it in the immediate window.) I just can't get to that next step of 'automation.' It could be my design, as I new to this pattern I'm totally amenable to the possibility that I've done this all wrong. Here's what I have...

I have a main window. It's a grid with 3 rows. The top row is a menu. The bottom row is a status bar. The middle is a stack panel where the content is dynamically loaded based on the menu selection.

I have 2 views that I am using to fill this stack panel. One has nothing more than a styled textbox in it (Help & About.) The other is itself a composite view: a search panel, a results grid and a detail panel all loaded into a dock manager frame.

In the main window code behind, when the user clicks a menu option, I clear the children of the stack panel, instantiate the view model, instantiate the view passing the view model into it and then add the new view into the children of the stack. This works fine, but I don't think it's consistent with the pattern.

As I mentioned I have the resource dictionary, but I don't know how to associate it with the stack panel. I assume that I have to use binding, but I can't figure out how to bind to the resource dictionary and/or how to tell it to change views on command.

I have read articles that have added all of the available view models to a read only list in a view model that essentially acts as the go between the main widow and the actual view models needed. This seems OK, but I don't understand why the resource dictionary is needed then. Moreover, these examples were wizard implementations and in that scenario this seems like a good approach, but I can't imagine doing that for an application with say 100 view models.

Again, sorry for my ignorance, but I was hoping that someone could point me in the right direction. As I said, I've read a ton of articles (Josh Smith, Dave Hill, etc.) and I still haven't made the connection, so I was hoping for some concrete guidance. (I do have WPF Unleashed on the way, but I was hoping to make some progress before then.)

Can anyone help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

司马昭之心 2024-11-10 14:26:55

有多种方法可以绑定视图模型。

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.在视图的构造函数中绑定

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

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

3.使用 ViewModelLocator 绑定

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

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

 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 实例)到窗口的数据上下文,则您正在将 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}}">

There are ways on how to bind your view models.

1. Create a static resource in the 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. Bind in View's constructor

I know you mentioned not using code behind but this is also an option. As long as you don't write any logic in the code behind then you're good.

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

3. Bind using ViewModelLocator

You might want to create a view model locator class that is in charge of giving your view the viewmodel that it needs.

Here's a simple example of a viewmodel locator class. The viewmodel locator class exposes some viewmodel properties. Then later on we will bind these properties to the data context of the views.

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

Then you can create a static resource of the viewmodel locator in the App.xaml to make it available to all the views within the app.

<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>

Then you can bind your view's data context to the viewmodel locator's property.

The example tells us that you are binding the MainVM property if the viewmodel locator, which is a MainViewModel instance, to the Window's data context.

<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}}">
勿忘心安 2024-11-10 14:26:55

我没有使用过WPF,但我使用过Silverlight,我相信它应该是差不多的。

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

例如 ViewModel:

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

View

[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。

I've not used WPF but I've used Silverlight and I believe it should be pretty much the same.

When I create my View I instantiated the required ViewModel within the View. I use MEF for Dependency Injection and create the Required VM that way, you might not want to go down that route but it could give you an idea.

e.g. ViewModel:

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

View

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

This way saves instantiating your VM and your V, just create your V and let that care about instantiating the VM and setting it's own DataContext.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文