MVVM - How do I Bind the View Model to the View
MVVM - How do I Bind the View Model to the View
问题
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?
回答1
There are ways on how to bind your view models.
1. Create a static resource in the XAML.
这是两个组合起来使用,定义了Window.Resources, 里面的key是MainVM。然后在Grid的DataContext里面绑定
<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
直接在构造函数里面绑定DataContext
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}}">
回答2
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.
作者:Chuck Lu GitHub |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2021-08-17 游戏术语
2021-08-17 the user account is not authorized for remote login
2020-08-17 乐刻健身房 间隔天数
2015-08-17 Linq打印
2015-08-17 .net framework client profile
2015-08-17 Resharper中注释代码的快捷键
2015-08-17 What does the number on the visual studio solution icon represent?