2015-10-05 331 views
1

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

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

我真的找到的唯一的文章是这篇文章Issues with IMutableDependencyResolver and Structuremap in ReactiveUI有人在写自己的整合。

所以给出了一些视图模型:

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>接口代码:

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 ?

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:

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

我也曾尝试在模块的初始化初始化啪:

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框架的好处的人。

回答

2

棱镜和RxUI和视图绑定上的不同语义。

Prism尝试为给定视图解析VM类型,而RxUI以相反方式解决此问题并为当前VM解析View。

你的实现是(几乎)工作:

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

这足以显示视图,如果添加AutoWireViewModel=True,棱镜将创建一个虚拟机实例,并将其设置到您的视图DataContext

要注意的是这行:

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

试图将ViewModel属性绑定到同一DataContext,并愉快地与空这样做,覆盖创建的实例/通过棱镜(这里是你的问题,我相信)设置。

简单地删除这个绑定的作品,但总体来看,它似乎并不是一个混合Prism和RxUI的好方法。

也许您可以看看RxUI RoutedViewHostViewModelViewHost,并将其中一个绑定到区域中。然后,RxUI视图解析将自动启动,并根据控件上设置的当前VM来刷新内部视图。这是当你需要注册你的意见,就像你做的那样:

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