2012-06-12 87 views
0

我對WPF MVVM(Light)非常陌生,我需要一些幫助。WPF MVVM Light TabControl中的主控細節,使用消息傳遞所選項目

什麼我是主從方案中,TabControl的在主視圖中,在第一個選項卡主視圖(ProductsView),並在以下選項卡的多個不同的細節視圖(例如的DetailsView)。

根據在ProductsView選擇(SelectedProduct)的項目,我想立即獲取在DetailsView項目,但沒有 - 只有當用戶點擊包含此信息查看TabItem的。從數據庫

所以取詳細數據應當用戶點擊相應的詳細資料標籤以某種方式推遲到一點(他可能不點擊它在所有)。

這裏是我的XAML:

<!-- Main View --> 
<UserControl x:Class="MyApp.Views.MainView"> 
    <TabControl> 
    <TabControl.Items> 
     <TabItem> 
     <views:ProductsView /> 
     </TabItem> 
     <TabItem> 
     <views:DetailsView /> 
     </TabItem> 
     <!-- More TabItems with details views --> 
    </TabControl.Items> 
    </TabControl> 
</UserControl> 

<!-- Products View --> 
<UserControl x:Class="MyApp.Views.ProductsView"> 
    <Grid DataContext="{Binding Source={StaticResource Locator}, Path=ProductsVM}"> 
    <DataGrid ItemsSource="{Binding Products}" SelectedItem="{Binding SelectedProduct}"> 
     <DataGridTextColumn Binding="{Binding Path=Model.ProductID}" Header="Product ID" /> 
    </DataGrid> 
    </Grid> 
</UserControl> 

<!-- Details View --> 
<UserControl x:Class="MyApp.Views.DetailsView"> 
    <Grid DataContext="{Binding Source={StaticResource Locator}, Path=DetailsVM.Details}"> 
    <StackPanel> 
     <TextBox Text="{Binding Path=Model.Field1}" /> 
     <TextBox Text="{Binding Path=Model.Field2}" /> 
    </StackPanel> 
    </Grid> 
</UserControl> 

和代碼:

public class ProductsViewModel : ViewModelBase 
{ 
    private ObservableCollection<Product> products; 
    public ObservableCollection<Product> Products 
    { 
     get 
     { 
      return products; 
     } 
     set 
     { // RaisePropertyChanged 
      Set("Products", ref products, value); 
     } 
    } 

    private Product selectedProduct; 
    public Product SelectedProduct 
    { 
     get 
     { 
      return selectedProduct; 
     } 
     set 
     { // RaisePropertyChanged and broadcast message of type PropertyChangedMessage<Product> 
      Set("SelectedProduct", ref selectedProduct, value, true); 
     } 
    } 

    public ProductsViewModel(IDataService dataService) 
    { 
     this.dataService = dataService; 
     Products = dataService.GetAllProducts(); 
    } 
} 

public class DetailsViewModel : ViewModelBase 
{ 
    private Details details; 
    public Details Details 
    { 
     get 
     { 
      return details; 
     } 
     set 
     { // RaisePropertyChanged 
      Set("Details", ref details, value); 
     } 
    } 

    public DetailsViewModel(IDataService dataService) 
    { 
     this.dataService = dataService; 
     Messenger.Default.Register<PropertyChangedMessage<Product>>(this, m => Details = dataService.GetDetails(m.NewValue.Model.ProductID)); 
    } 
} 

現在這個工作,但產品選擇後,所有的細節都在所有的細節選項卡,立即取出。 我一直在想,也許當用戶點擊MainView中的一個選項卡時,MainViewModel應該發送一個帶有Tab鍵索引的消息給ProductviewModel,然後ProductviewModel應該發送另一個消息將SelectedProduct傳遞給基於tab索引的當前請求tabitem的DetailsViewModel,會更新它的詳細數據。

但我怎麼會只發送消息到當前請求的tabitem/DetailsView基於標籤索引,而不是所有的?

而且這種往返方式聽起來太複雜了。你能給我一些建議嗎? 或者這是完全錯誤的? 也許有另一個更簡單更優雅的解決方案呢?

回答

0

我想你正在尋找的是經典的酒吧/子模型。當用戶單擊一個選項卡控件時,會引發一個名爲RequestViewOfProductDetails的事件。您將設立在主視圖模型像這樣的東西發佈:

public MasterViewModel() 
{ 
    Messenger.Default.Send<RequestViewOfProductDetails>(_selectedProduct); 
} 

然後,在您的詳細信息查看模式,你將建立視圖模型對這一事件作出迴應:

Messenger.Default.Register<RequestViewOfProductDetails>(this, delegate(Product prod) 
{ 
    // fetch details 
}); 

然後,您將爲每個詳細信息類型設置一個消息,在每個選項卡項目上發佈該特定詳細信息事件。單調乏味,我知道,但是將所有標籤分開。現在如果是我,我會做一些不同的事情。我會在後臺工作線程上執行請求,因此您可以避免針對特定選項卡的這種頭痛。選擇產品後,只需派遣獲取者異步填充所有選項卡,並且事情透明。

3

通常我會有我的ViewModel跟蹤TabsSelectedTab爲好,只會加載當前選項卡中SelectedTabPropertyChanged事件

事情是這樣的:

// Not expanding these to full properties with property change 
// notifications for sake of simplicity here 
ObservableCollection<ViewModelBase> Tabs; 
ViewModelBase SelectedTab; 

void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    if (e.PropertyName == "SelectedTab") 
    { 
     if (SelectedTab is IDetailsTab) 
      ((IDetailsTab)SelectedTab).LoadProduct(SelectedProduct); 

      // Or depending on your structure: 
      var productsTab = Tabs[0] as ProductsViewModel; 
      ((IDetailsTab)SelectedTab).LoadProduct(productsTab.SelectedProduct); 
    } 
} 

和你的XAML看起來像這樣:

<TabControl ItemsSource="{Binding Tabs}" SelectedItem="{Binding SelectedTab}"> 
    <TabControl.Resources> 
     <DataTemplate DataType="{x:Type local:ProductsViewModel}"> 
      <local:ProductsView /> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type local:DetailsViewModel}"> 
      <local:DetailsView /> 
     </DataTemplate> 
    </TabControl.Resources> 
</TabControl> 
0

當您的詳細信息選項卡被選中時,刷新da通過這個事件在Tab上。通過事件參數選擇產品。

相關問題