2015-10-05 2 views
1

У нас есть существующее приложение WPF, которое использует PRISM (6.x) с Unity (3.5.x) для DI. Мы собираемся добавить больше функциональности для этого приложения и хотели бы начать использовать ReactiveUI для любых новых модулей, которые нам нужно реализовать.Как использовать ReactiveUI внутри модуля PRISM

Мы надеялись минимизировать кривую обучения и продолжать использовать Unity и DI для наших ViewModels; однако ReactiveUI использует Splat для местоположения View, и до сих пор мне не удалось заставить мой модуль ReactiveUI фактически отображаться в регионе PRISM в нашем основном приложении, независимо от того, что я пробовал.

Единственная статья, которую я действительно нашел, это сообщение Issues with IMutableDependencyResolver and Structuremap in ReactiveUI, где кто-то писал собственную интеграцию.

Поэтому, учитывая некоторые 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>:

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

Я также попытался инициализация Splat в 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.

ответ

2

Призма и RxUI и другая семантика на привязке вида.

Prism пытается разрешить тип виртуальной машины для данного вида, тогда как RxUI делает это наоборот и разрешает представление для текущей виртуальной машины.

Ваша реализация (почти) рабочий:

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

Этого достаточно, чтобы отобразить вид, а если добавить AutoWireViewModel=True, Prism создаст экземпляр VM и установить его на ваш взгляд DataContext.

Остерегайтесь, что эта линия:

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

Попытки связать ViewModel свойства к тому же DataContext, и с удовольствием делает это с нулем, перекрывая экземпляр, созданный/установленный Prism (вот ваш вопрос я считаю) ,

Просто удалите эту привязку, но в целом это не кажется хорошим способом смешивания Prism и RxUI.

Возможно, вместо этого вы могли бы изучить RxUI RoutedViewHost и ViewModelViewHost и связать один из них в регионе. Затем разрешение разрешения RxUI автоматически включается и обновляет внутренние представления в зависимости от текущей виртуальной машины, установленной на элементе управления. Это когда вам необходимо зарегистрировать свое мнение, как и вы:

Locator.CurrentMutable.Register(() => new HelloWorldView(), typeof(IViewFor<HelloWorldViewModel>)); 
Смежные вопросы