打开新窗口时,通过IDialogService将参数发送到ViewModel

时间:2016-04-16 12:58:32

标签: c# wpf mvvm

我有PersonViewModelDepartmentViewModel和他们的PersonViewDepartmentView

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> persons打开新窗口时,如何将DepartmentViewModel发送到IDialogService

1 个答案:

答案 0 :(得分: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;
    }
}

我的所有虚拟机都有一个IUiService属性,当我调用它的Init方法时会设置该属性。

在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中所做的基本相同。

因此,当您想要Show来自其他ViewModel的ViewModel时,请调用this.UiService.Show(new YourVm(parameters..));

然后,

IUiService.Show将使用ViewLocator确定VM的窗口类型并创建一个新窗口。它还使用该窗口为新VM分配IUiService。

IDialogReturnVm<T>是一个包含您在Vm中设置的单个属性T ReturnInfo{get; private set;}的接口。

这使View和ViewModel保持良好分离,同时仍允许您将参数传递给ViewModel。我甚至将ViewModel放在不同的程序集中。 IUiService在该程序集中定义,并且实现:UiService在主程序集中定义。