2012-06-12 45 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上。通过事件参数选择产品。

相关问题