2010-09-28 63 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'依賴注入我。你不必這樣做,但我喜歡它的工作原理。