淡若轻风

博客园 首页 新随笔 联系 订阅 管理
  52 随笔 :: 0 文章 :: 0 评论 :: 6281 阅读
Prism for WPF 中,ViewModelLocator 是实现 View 和 ViewModel 自动关联 的核心机制。
当你在 XAML 中设置:
prism:ViewModelLocator.AutoWireViewModel="True"

Prism 会根据 约定(Convention) 自动解析并绑定 View 和对应的 ViewModel,而不需要手动实例化 ViewModel。

📌 实现原理概述

    1. 依附属性(Attached Property)机制
      Prism 通过依附属性 AutoWireViewModel 监听 View 的加载(Loaded 事件),在 View 加载时触发自动绑定。

    2. ViewModel 解析与创建
      Prism 通过约定(View/ViewModel 命名规则)和 IoC 容器(如 Unity、DryIoc)解析出 ViewModel 类型,并创建实例。

    3. ViewModel 设置
      Prism 将解析得到的 ViewModel 设置为 View 的 DataContext,实现 View 和 ViewModel 绑定。

 

📖 源码解析

1️⃣ AutoWireViewModel 属性注册

Prism 在 ViewModelLocator 类中定义了一个 依附属性,用于自动绑定:

public static readonly DependencyProperty AutoWireViewModelProperty =
    DependencyProperty.RegisterAttached(
        "AutoWireViewModel",
        typeof(bool?),
        typeof(ViewModelLocator),
        new PropertyMetadata(null, AutoWireViewModelChanged)
    );
  • DependencyProperty.RegisterAttached 是 WPF 定义依附属性的 API。
  • AutoWireViewModelChanged 是属性变更时的回调函数,触发 ViewModel 自动绑定逻辑。

2️⃣ 属性变更触发逻辑

AutoWireViewModel 被设置为 True 时,执行以下绑定过程:

private static void AutoWireViewModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if ((bool?)e.NewValue == true)
    {
        SetAutowireViewModel(d);
    }
}
  • d 表示目标对象(通常是 FrameworkElement)。
  • SetAutowireViewModel(d) 是关键绑定逻辑,负责解析和注入 ViewModel。

3️⃣ ViewModel 自动绑定逻辑

private static void SetAutowireViewModel(object view)
{
    var viewModel = GetViewModelForView(view);
    if (viewModel != null)
    {
        ((FrameworkElement)view).DataContext = viewModel;
    }
}
  1. 调用 GetViewModelForView() 解析 ViewModel 类型并创建实例。
  2. 将 ViewModel 设置为 View 的 DataContext,完成绑定。

🔍 ViewModel 解析逻辑

(1) 命名约定解析

Prism 默认使用以下命名规则解析 ViewModel:

  • ViewMainWindow
  • ViewModelMainWindowViewModel

代码实现如下:

复制代码
protected static object GetViewModelForView(object view)
{
    var viewType = view.GetType();
    var viewName = viewType.FullName;
    var viewAssemblyName = viewType.GetTypeInfo().Assembly.FullName;

    // 默认根据约定推断 ViewModel 名称
    var viewModelName = viewName.Replace("View", "ViewModel");
    var viewModelType = Type.GetType($"{viewModelName}, {viewAssemblyName}");

    return viewModelType != null ? Activator.CreateInstance(viewModelType) : null;
}
复制代码
  • ViewModel 名称推导:将 View 替换为 ViewModel
  • Type.GetType:根据完全限定名反射获取类型。
  • Activator.CreateInstance:使用无参数构造函数创建 ViewModel 实例。

(2) 依赖注入解析(IoC 容器)

如果你使用 Prism 的依赖注入(Unity、DryIoc 等),Prism 优先通过 IoC 容器解析 ViewModel:

var viewModelType = Type.GetType(viewModelName);
if (viewModelType != null && ContainerLocator.Container != null)
{
    return ContainerLocator.Container.Resolve(viewModelType);
}
  • ContainerLocator.Container:Prism 全局 IoC 容器。
  • Resolve():根据类型解析 ViewModel,支持构造函数注入。

📊 工作流程总结

  1. View 加载:View 被实例化并加载到界面。
  2. 属性变化回调:设置 AutoWireViewModel="True" 触发绑定逻辑。
  3. ViewModel 解析
    • 命名约定(View → ViewModel)查找 ViewModel 类型。
    • 使用 IoC 容器(若有)解析 ViewModel,支持依赖注入。
  4. DataContext 设置:将 ViewModel 作为 DataContext 设置到 View

📚 示例:完整实现

1️⃣ MainWindow.xaml

复制代码
<Window x:Class="PrismDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True">
    <Grid>
        <TextBlock Text="{Binding Title}" FontSize="24" />
    </Grid>
</Window>
复制代码

2️⃣ MainWindowViewModel.cs

复制代码
public class MainWindowViewModel : BindableBase
{
    private string _title = "Hello Prism!";
    public string Title
    {
        get => _title;
        set => SetProperty(ref _title, value);
    }
}
复制代码

3️⃣ App.xaml.cs

复制代码
public class App : PrismApplication
{
    protected override Window CreateShell() => Container.Resolve<MainWindow>();

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.RegisterSingleton<MainWindowViewModel>();
    }
}
复制代码

📌 自定义 View-ViewModel 绑定策略

你可以通过覆盖 ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver 自定义解析规则。例如,使用 VM 后缀

ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver(viewType =>
{
    var viewName = viewType.FullName.Replace("View", "VM");
    return Type.GetType(viewName);
});

 

总结
prism:ViewModelLocator.AutoWireViewModel 通过 依附属性 触发,结合 View/ViewModel 命名约定IoC 容器解析

实现 View 和 ViewModel 的自动绑定。

posted on   淡若轻风  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示