如何在 PRISM 模块中使用 ReactiveUI [英] How to use ReactiveUI inside a PRISM module

查看:44
本文介绍了如何在 PRISM 模块中使用 ReactiveUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个现有的 WPF 应用程序,它使用 PRISM (6.x) 和 Unity (3.5.x) 进行 DI.我们将为此应用程序添加更多功能,并希望开始将 ReactiveUI 用于我们需要实现的任何新模块.

We have an existing WPF application that uses PRISM (6.x) with Unity (3.5.x) for DI. We are going to be adding more functionality to this application and would like to start utilizing ReactiveUI for any new modules that we need to implement.

我们希望尽量减少学习曲线,并继续为我们的 ViewModel 使用 Unity 和 DI;然而,ReactiveUI 使用 Splat 查看位置,到目前为止我有无论我尝试过什么,都无法让我的 ReactiveUI 模块实际显示在我们主应用程序的 PRISM 区域中.

We were hoping to minimize the learning curve and continue to utilize Unity and DI for our ViewModels; however, ReactiveUI uses Splat for View location and so far I have not been able to get my ReactiveUI module to actually display in a PRISM region within our main application regardless of what I have tried.

我真正找到的唯一一篇文章是这篇文章ReactiveUI 中的 IMutableDependencyResolver 和 Structuremap 的问题,其中有人写了他们的自己的集成.

The only article that I have really found was this post Issues with IMutableDependencyResolver and Structuremap in ReactiveUI where someone was writing their own integration.

所以给定一些 ViewModel:

So given some ViewModel:

public class HelloWorldViewModel : ReactiveObject 
{
    string title = "Hello ReactiveUI";
    public string Title
    {
        get { return title; }
        set { this.RaiseAndSetIfChanged(ref title, value); }
    }
}

及其对应的视图:

<UserControl x:Class="PBI.ObjectMover.ReactSample.Views.HelloWorldView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
  <Grid>
    <TextBlock Text="{Binding Title}" Foreground="Green" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Calibri" FontSize="24" FontWeight="Bold"></TextBlock>            
  </Grid>
</UserControl>

以及实现IViewFor<T>接口的视图代码:

And the view's code behind implementing the IViewFor<T> interface:

public partial class HelloWorldView : UserControl, IViewFor<HelloWorldViewModel>
{
    public HelloWorldView()
    {
        InitializeComponent();

        this.WhenAnyValue(x => x.ViewModel).BindTo(this, x => x.DataContext);
    }

    public HelloWorldViewModel ViewModel
    {
        get { return (HelloWorldViewModel)GetValue(ViewModelProperty); }
        set { SetValue(ViewModelProperty, value); }
    }

    public static readonly DependencyProperty ViewModelProperty =
        DependencyProperty.Register("ViewModel", typeof(HelloWorldViewModel), typeof(HelloWorldView), new PropertyMetadata(null));

    object IViewFor.ViewModel { get; set; }
}

IModule 初始化需要什么才能将 ReactiveUI ViewModel 和 View 连接起来?

What is needed in the IModule initialization to get the ReactiveUI ViewModel and View hooked up?

public class ReactSampleModule : IModule
{
    private readonly IRegionManager RegionManager;
    public ReactSampleModule(IUnityContainer container, IRegionManager regionManager)
    {
        this.RegionManager = regionManager;
    }

    public void Initialize()
    {
        /* What do I need here to initialize ReactiveUI or Unity? */

        /* Register views */
        this.RegionManager.RegisterViewWithRegion("RightRegion", typeof(HelloWorldView)); 
    }
}

我尝试将棱镜定位器添加到视图的 XAML:

I have tried adding the prism locator to the View's XAML:

<UserControl x:Class="PBI.ObjectMover.ReactSample.Views.HelloWorldView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:prism="http://prismlibrary.com/"
         prism:ViewModelLocator.AutoWireViewModel="True">

我也尝试在模块的初始化中初始化 Splat:

I have also tried initializing Splat in the module's initialize:

    public void Initialize()
    {
        /* Register types */
        Locator.CurrentMutable.InitializeSplat();
        Locator.CurrentMutable.InitializeReactiveUI();
        Locator.CurrentMutable.Register(() => new HelloWorldView(), typeof(IViewFor<HelloWorldViewModel>));

        /* Register views */
        this.RegionManager.RegisterViewWithRegion("RightRegion", typeof(HelloWorldView)); 
    }

到目前为止,一切都没有奏效,但我怀疑我们是唯一看到将 PRISM 的模块化架构与 ReactiveUI 框架结合使用的好处的人.

So far nothing has worked but I doubt that we are the only ones that see the benefit of using PRISM's modular architecture with ReactiveUI's framework.

推荐答案

Prism 和 RxUI 以及视图绑定的不同语义.

Prism and RxUI and different semantics on view binding.

Prism 尝试为给定视图解析 VM 类型,而 RxUI 则相反,并为当前 VM 解析视图.

Prism tries to resolve a VM type for a given view, whereas RxUI does it the other way around and resolves View for the current VM.

您的实现(几乎)有效:

Your implementation is (almost) working:

this.RegionManager.RegisterViewWithRegion("RightRegion", typeof(HelloWorldView));

这足以显示视图,如果您添加 AutoWireViewModel=True,Prism 将创建一个 VM 实例并将其设置为您的视图 DataContext.

This is enough to display the view, and if you add AutoWireViewModel=True, Prism will create a VM instance and set it to your view DataContext.

注意这一行:

this.WhenAnyValue(x => x.ViewModel).BindTo(this, x => x.DataContext);

尝试将 ViewModel 属性绑定到相同的 DataContext,并且很乐意使用 null 这样做,覆盖由 Prism 创建/设置的实例(我相信这是您的问题).

Attempts to bind the ViewModel property to the same DataContext, and will happily do so with null, overriding the instance created/set by Prism (here's your issue I believe).

简单地删除这个绑定是可行的,但总的来说,它似乎不是混合 Prism 和 RxUI 的好方法.

Simply removing this binding works, but overall it doesn't seem a nice way of mixing Prism and RxUI.

也许您可以查看 RxUI RoutedViewHostViewModelViewHost 并将其中之一绑定到区域中.然后 RxUI 视图解析将自动启动,并根据控件上设置的当前 VM 刷新内部视图.这是您需要注册您的观点的时候,就像您所做的一样:

Maybe instead you could look into RxUI RoutedViewHost and ViewModelViewHost and bind one of these into the region instead. Then RxUI view resolving will kick in automatically, and refresh the inner views depending on the current VM set on the control. This is when you need to register your views, like you did:

Locator.CurrentMutable.Register(() => new HelloWorldView(), typeof(IViewFor<HelloWorldViewModel>));

这篇关于如何在 PRISM 模块中使用 ReactiveUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆