DataContext连接View与ViewModel挂钩。
有3种方法可以将View与ViewModel连接起来。
1.在XAML中
2.后台代码分配
3.视图模型定位
我们的重点是如何绑定DataContext,因此我们不会在本文中关注样式或数据。
我们需要2个文件夹,每个文件夹用于View和ViewModel。然后我创建了两个UserControl,LoginView和RegisterView以及它们各自的ViewModel1.LoginViewModel和2.RegisterViewModel。请参阅图1以了解结构。
笔记
我们必须遵守这里的标准。每个视图都以术语“视图”结束,例如LoginView,每个视图模型都以术语“视图模型”结束,例如LoginViewModel。
在XAML中绑定DataContext
我们将在这个实验中使用LoginView
第1步
将LoginViewModel的命名空间添加到LoginVIew.xaml。
xmlns:local="clr-namespace:WPF_DataContext.VIewModel"
使用UserControl的DataContext属性来分配ViewModel
就这样。现在要确认View是否与ViewModel连接,我们可以在LoginView.xaml中添加TextBlock。完成后,您的最终LoginView.xaml将如下所示。
请注意,TextBlock与属性名称Message绑定,为此我们需要在LoginVIewModel中创建此字符串类型属性。让我们在构造函数中为Message赋值。
在构造函数中分配值或调用API是一种不好的做法,您应该始终使用具有多线程的方法来调用或更新数据。但由于这是一个小例子,我们将直接在构造函数中赋值。
namespace WPF_DataContext.VIewModel
{
public class LoginViewModel
{
private string _message;
public string Message
{
get { return _message; }
set { _message = value; }
}
public LoginViewModel()
{
_message = "Login View Model is Connected..";
}
}
}
只需调用MainWindow.xaml中的LoginView UserControl,如下。
现在,运行您的项目。您将能够看到如图所示的输出,
在这种方法中,我们将使用RegisterView。 打开RegisterView的代码隐藏类,即RegisterView.xaml.cs并设置this.DataContext值。
this.DataContext = new RegisterViewModel();
您的最终 RegiserView.xaml.cs 将类似于以下代码片段,
using System.Windows.Controls;
using WPF_DataContext.VIewModel;
namespace WPF_DataContext.View
{
///
/// Interaction logic for RegisterView.xaml
///
public partial class RegisterView : UserControl
{
public RegisterView()
{
InitializeComponent();
this.DataContext = new RegisterViewModel();
}
}
}
现在我们在 View 上有了 TextBlock,我们已经在代码隐藏中设置了 DataContext,我们需要在 ViewModel 中为该 TextBlock 分配值。
以下 RegisterView.xaml 显示了 TextBlock 的外观,以下代码片段显示了 RegisterViewModel 的外观。
RegisterView.xaml
RegisterViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPF_DataContext.VIewModel
{
public class RegisterViewModel
{
private string _message;
public string Message
{
get { return _message; }
set { _message = value; }
}
public RegisterViewModel()
{
_message = "Register View Model is Connected..";
}
}
}
最后将Mainwindow.xaml中的LoginView替换为RegisterView
ViewModelLocator 集中代码以连接View和ViewModel。这意味着它为我们提供了将 View 与 ViewModel 绑定的松耦合方式,通过这种方法,View 不需要对它所连接的 ViewModel 进行硬编码。所以基本上我们用五步方法自动化整个过程,
所有这些步骤都发生在运行时,这就是为什么 View 在编译时不必担心它的 ViewModel 绑定。
现在我们已经确定了这个逻辑,我们可以简单地将它包装在一个方法中,然后重用相同的方法。接下来,我们需要弄清楚如何从 View 调用这个方法,并且有一个简单的方法可以做到这一点,这可以通过附加属性的帮助来实现。
让我们通过添加一个名为 ViewModelLocator 的类来开始这个过程,
您最终的 ViewModelLocator 将如下所示:注意:检查代码中的摘要和注释以了解其含义。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace WPF_DataContext
{
public static class ViewModelLocator
{
///
/// Gets AutoWireViewModel attached property
///
///
///
public static bool GetAutoWireViewModel(DependencyObject obj)
{
return (bool)obj.GetValue(AutoWireViewModelProperty);
}
///
/// Sets AutoWireViewModel attached property
///
///
///
public static void SetAutoWireViewModel(DependencyObject obj, bool value)
{
obj.SetValue(AutoWireViewModelProperty, value);
}
///
/// AutoWireViewModel attached property
///
public static readonly DependencyProperty AutoWireViewModelProperty =
DependencyProperty.RegisterAttached("AutoWireViewModel",
typeof(bool), typeof(ViewModelLocator),
new PropertyMetadata(false, AutoWireViewModelChanged));
///
/// Step 5 approach to hookup View with ViewModel
///
///
///
private static void AutoWireViewModelChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
if (DesignerProperties.GetIsInDesignMode(d)) return;
var viewType = d.GetType(); //Step 1: Ex- LoginView
var viewModelTypeName = (viewType).ToString().Replace("View", "ViewModel"); //Step 2: Ex- LoginViewModelName
var viewModelType = Type.GetType(viewModelTypeName); // step 3: Ex- get the type of LoginViewModel
var viewModel = Activator.CreateInstance(viewModelType); // step 4: Ex- create an instance of LoginViewModel
((FrameworkElement)d).DataContext = viewModel; // step 5: Ex- LoginView's DataContext is set to LoginViewModel
}
}
}
到目前为止,我们已经创建了一个附加属性,它使用它的事件调用我们的 AutoWire 逻辑。这是一种布尔类型的附加属性,当它设置为 true 时将触发事件。让我们看看如何在视图中做到这一点。
首先,将 LoginViewModel 的命名空间添加到您的视图中
为了确认它可以同时处理多个视图,让我们在 RegisterView 中也做一些更改。并且不要忘记注释我们在 RegisterView.xaml.cs 的代码隐藏中设置的 DataContext。
RegisterView.xaml
请将两个视图都添加到 MainWindow.xaml