2010-09-28 92 views
1

我有两个有关ViewModels之间通信的问题。ViewModels之间的通信

我正在开发一个客户管理程序。我正在使用Laurent Bugnion的MVVM Light框架。

  1. 在主页面中,有一个客户列表。当每个客户被点击时,子窗口会显示关于该客户的信息。用户应该能够同时打开多个子窗口并比较客户之间的信息。如何以MVVM友好的方式将客户对象从主页面的ViewModel传递到子窗口的ViewModel?

  2. 在显示客户信息的子窗口中,有许多选项卡,每个选项卡都显示不同的信息区域。我为每个选项卡创建了独立的ViewModels。你怎么能分享每个标签的视图模型之间的当前客户信息?

非常感谢!

+0

这确实应该被创建为两个单独的问题。 – 2010-09-28 11:36:51

回答

0

在我的项目中,我也将ViewModels传递给子窗口。我在后面的子窗口代码中创建ViewModel的依赖项属性,并在此属性的设置器中将ViewModel传递给我的子窗口的ViewModel。这意味着你正在为你的子窗口创建一个单独的ViewModel类。

要回答第二个问题,您可以让您的子窗口的ViewModel包含每个选项卡关心的属性,但其数据上下文仍与子窗口的数据上下文相同,以便他们可以访问共享属性。这实际上很简单,因为它们自动获取子窗口的数据上下文。

下面是一个说明上述两个概念的例子。

子窗口视图DetailsWindow.xaml(请注意,我在命名我的孩子的窗口视图* Window.xaml而不是* View.xaml的习惯已经得到)

<controls:ChildWindow x:Class="DetailsWindow" 
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
         xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
         xmlns:Views="clr-namespace:Views" 
         Title="Details" 
         DataContext="{Binding DetailsWindowViewModel, Source={StaticResource Locator}}" 
         > 
    <Grid> 
     <sdk:TabControl> 
      <sdk:TabItem Header="First Tab" Content="{Binding FirstTabContent}" /> 
      <sdk:TabItem Header="Second Tab" Content="{Binding SecondTabContent}" /> 
     </sdk:TabControl> 
    </Grid> 
</controls:ChildWindow> 

子窗口视图的背后DetailsWindow.xaml.cs及其接口IDetailsWindow.cs

public partial class DetailsWindow : ChildWindow, IDetailsWindow 
{ 
    private IDetailsWindowViewModel ViewModel 
    { 
     get { return this.DataContext as IDetailsWindowViewModel; } 
    } 

    public DetailsWindow() 
    { 
     InitializeComponent(); 
    } 

    #region Customer dependency property 

    public const string CustomerViewModelPropertyName = "Customer"; 

    public ICustomerViewModel Customer 
    { 
     get 
     { 
      return (ICustomerViewModel)GetValue(CustomerViewModelProperty); 
     } 
     set 
     { 
      SetValue(CustomerViewModelProperty, value); 
      if (ViewModel != null) 
      { 
       ViewModel.Customer = value; 
      } 
     } 
    } 

    public static readonly DependencyProperty CustomerViewModelProperty = DependencyProperty.Register(
     CustomerViewModelPropertyName, 
     typeof(ICustomerViewModel), 
     typeof(CustomerDetailsWindow), 
     null); 

    #endregion 
} 

public interface IDetailsWindow 
{ 
    ICustomerViewModel Customer { get; set; } 
    void Show(); 
} 

子窗口视图国防部代码埃尔DetailsWindowViewModel.cs及其接口IDetailsWindowViewModel

public class DetailsWindowViewModel : ViewModelBase, IDetailsWindowViewModel 
{ 
    public DetailsWindowViewModel(IMessenger messenger) 
     : base(messenger) 
    { 
    } 

    #region Properties 

    #region Customer Property 

    public const string CustomerPropertyName = "Customer"; 

    private ICustomerViewModel _customer; 

    public ICustomerViewModel Customer 
    { 
     get { return _customer; } 
     set 
     { 
      if (_customer == value) 
       return; 

      var oldValue = _customer; 
      _customer = value; 
      RaisePropertyChanged(CustomerPropertyName, oldValue, value, true); 
     } 
    } 

    #endregion 

    #region FirstTabContent Property 

    public const string FirstTabContentPropertyName = "FirstTabContent"; 

    private FrameworkElement _firstTabContent; 

    public FrameworkElement FirstTabContent 
    { 
     get { return _firstTabContent; } 
     set 
     { 
      if (_firstTabContent == value) 
       return; 

      _firstTabContent = value; 
      RaisePropertyChanged(FirstTabContentPropertyName); 
     } 
    } 

    #endregion 

    #region SecondTabContent Property 

    public const string SecondTabContentPropertyName = "SecondTabContent"; 

    private FrameworkElement _secondTabContent; 

    public FrameworkElement SecondTabContent 
    { 
     get { return _secondTabContent; } 
     set 
     { 
      if (_secondTabContent == value) 
       return; 

      _secondTabContent = value; 
      RaisePropertyChanged(SecondTabContentPropertyName); 
     } 
    } 

    #endregion 

    #endregion 
} 

public interface IDetailsWindowViewModel 
{ 
    ICustomerViewModel Customer { get; set; } 
    FrameworkElement FirstTabContent { get; set; } 
    FrameworkElement SecondTabContent { get; set; } 

    void Cleanup(); 
} 

而且你可以从你的MainPageViewModel.cs显示子窗口这样。

public class MainViewModel : ViewModelBase, IMainViewModel 
{ 
    private readonly IDetailsWindow _detailsWindow; 

    public MainViewModel(IMessenger messenger, IDetailsWindow DetailsWindow) 
     : base(messenger) 
    { 
     _detailsWindow = DetailsWindow; 
    } 

    private void DisplayCustomerDetails(ICustomerViewModel customerToDisplay) 
    { 
     _detailsWindow.Customer = customerToDisplay; 
     _detailsWindow.Show(); 
    } 
} 

请注意,我对所有我的视图模型和子窗口的创建接口和我在ViewModelLocator使用DI/IoC容器,让所有我的ViewModels'依赖注入我。你不必这样做,但我喜欢它的工作原理。