2016-04-16 43 views
0

我有PersonViewModel,DepartmentViewModel及其PersonView,DepartmentView當打開新窗口時,通過IDialogService發送參數給ViewModel

PersonViewModel有空的構造,但是DepartmentViewModel有一個參數:

public class DepartmentViewModel 
{ 
    public DepartmentViewModel(ObservableCollection<Person> persons) 
    {} 
} 

我用下面的服務來打開新窗口:

public interface IDialogService<T> 
{ 
    void Show(IUnityContainer unityContainer); 
    void ShowDialog(IUnityContainer unityContainer); 
} 

public class DialogService<T> : IDialogService<T> where T : Window 
{ 
    public void Show(IUnityContainer unityContainer) 
    {    
    var container = unityContainer; 
    container.Resolve<T>().Show(); 
    } 

    public void ShowDialog(IUnityContainer unityContainer) 
    {    
     var container = unityContainer;    
     container.Resolve<T>().ShowDialog();    
    } 
} 

上述服務的工作真的很好。到目前爲止,它工作正常,直到我想發送參數DepartmentViewModel

App.xaml.cs擁有所有的東西實例OnStartup()方法裏面的ViewModels:

protected override void OnStartup(StartupEventArgs e) 
{ 
    _container = new UnityContainer(); 
    _container.RegisterType<IViewMainWindowViewModel, MainWindow>(); 
    _container.RegisterType<IViewMainWindowViewModel, MainViewModel>(); 
    _container.RegisterType<IViewPersonViewModel, PersonView>(); 
    _container.RegisterType<IViewPersonViewModel, PersonViewModel>(new ContainerControlledLifetimeManager()); 
    _container.RegisterType<IViewDepartmentViewModel, DepartmentView>(); 
    _container.RegisterType<IViewDepartmentViewModel, DepartmentViewModel>(new ContainerControlledLifetimeManager()); 
    //types 
    _container.RegisterType(typeof(IDialogService<>), typeof(DialogService<>)); 
    _container.Resolve<MainWindow>().Show(); 
} 

我的問題是我怎麼能發送參數DepartmentViewModel當我從PersonViewModel打開新窗口?

我的代碼從PersonViewModel打開新窗口:

private readonly IDialogService<DepartmentView> _dialogDepartmentView; 

public void ContinueCommand_DoWork(object obj) 
{ 
    //want to send "persons" to departmentViewModel 
    ObservableCollection<Person> persons = new ObservableCollection<Person>();   
    // Open new dialog  
    _dialogDepartmentView.ShowDialog(_unityContainer); 
} 

我如何發送ObservableCollection<Person> personsDepartmentViewModel當我通過IDialogService打開新窗口?

+0

Argh。 'ServiceLocator'反模式遍及你的代碼。這就是說,你有多少個'DepartmentViewModel'實例?這是您決定採用哪種方式解決問題的決定性因素。 – code4life

+0

@ code4life只是DepartmentViewModel的一個實例。反模式意味着不好? – StepUp

+1

應該儘量不要使用它,說實話。 – code4life

回答

1

也許你需要一個新的Dialog/UIService。

下面是我用來達到與您相同效果的UiService。我不使用任何IoC容器。 ViewLocator是一個簡單的類,具有從Vm類型到View類型的字典映射。不過,您可以將ViewLocator替換爲所需的任何「ServiceLocator」。

public interface IUiService { 
    void Close(); 
    void Show<TVm>(TVm vm) where TVm : ViewModel; 
    public T ShowDialog<T, TVm>(TVm vm) 
     where T : class 
     where TVm : ViewModel, IDialogReturnVm<T>; 
} 

public class UiService : IUiService 
{ 
    private readonly Window window; 

    public UiService(Window window) 
    { 
     this.window = window; 
    } 

    public void Close() 
    { 
     this.window.Close(); 
    } 

    public void Show<TVm>(TVm vm) where TVm : ViewModel 
    { 
     Type windowType = ViewLocator.GetViewType<TVm>() 

     var wnd = (Window)Activator.CreateInstance(windowType); 

     wnd.DataContext = vm; 
     wnd.Owner = Application.Current.MainWindow; 
     vm.Init(new UiService(wnd)); 
     wnd.Show(); 
    } 

    public T ShowDialog<T, TVm>(TVm vm) 
     where T : class //T is the type of imformation which the Vm will "return" when it's window is closed. 
     where TVm : ViewModel, IDialogReturnVm<T> 
    { 
     Type windowType = ViewLocator.GetViewType<TVm>() 

     var wnd = (Window)Activator.CreateInstance(windowType); 

     wnd.DataContext = vm; 
     wnd.Owner = Application.Current.MainWindow; 
     vm.Init(new UiService(wnd)); 
     wnd.ShowDialog(); 
     return vm.ReturnInfo; 
    } 
} 

我的虛擬機的所有有,當我把它稱爲是Init方法,設置了IUiService屬性。

在AppStartup,當我想打開我的第一個窗口,我做的:

Type windowType = ViewLocator.GetViewType<MainVm>() 

var wnd = (Window)Activator.CreateInstance(windowType); 

wnd.DataContext = new MainVm(); 
vm.Init(new UiService(wnd)); 
wnd.Show(); 

基本相同,我在做UiService.Show

所以,當你想從另一個ViewModel的Show一個ViewModel,你可以撥打this.UiService.Show(new YourVm(parameters..));

IUiService.Show然後將使用ViewLocator確定VM的窗口類型並創建一個新窗口。它還使用該窗口爲新VM分配IUiService。

IDialogReturnVm<T>是一個界面,其中包含您在Vm中設置的單個屬性T ReturnInfo{get; private set;}

這可以使View和ViewModel非常好地解耦,同時仍然允許您將參數傳遞給ViewModel。我甚至有我的ViewModels在不同的程序集中。在該程序集中定義了IUiService,並且在主程序集中定義了實現:UiService

相關問題