.net WPF MVVM Light master详细信息在TabControl中,使用消息传递所选项目
我是WPF MVVM(Light)的新手,我需要一些帮助 我拥有的是一个主-细节场景,主视图中的TabControl,第一个选项卡中的主视图(ProductsView),以及以下选项卡中的多个不同细节视图(例如DetailsView) 根据ProductsView中选择的项目(SelectedProduct),我希望在DetailsView中获取项目,但不是立即获取-仅当用户单击包含此详细信息视图的选项卡item时 因此,从数据库获取细节数据应该以某种方式推迟到用户单击适当的细节选项卡时(他可能根本没有单击它) 这是我的xaml:.net WPF MVVM Light master详细信息在TabControl中,使用消息传递所选项目,.net,wpf,mvvm,mvvm-light,message,.net,Wpf,Mvvm,Mvvm Light,Message,我是WPF MVVM(Light)的新手,我需要一些帮助 我拥有的是一个主-细节场景,主视图中的TabControl,第一个选项卡中的主视图(ProductsView),以及以下选项卡中的多个不同细节视图(例如DetailsView) 根据ProductsView中选择的项目(SelectedProduct),我希望在DetailsView中获取项目,但不是立即获取-仅当用户单击包含此详细信息视图的选项卡item时 因此,从数据库获取细节数据应该以某种方式推迟到用户单击适当的细节选项卡时(他可能
<!-- 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));
}
}
公共类产品viewmodel:ViewModelBase
{
私人可观测收集产品;
公共可观测收集产品
{
得到
{
退货产品;
}
设置
{//RaisePropertyChanged
设置(“产品”、参考产品、价值);
}
}
私人产品选择产品;
公共产品精选产品
{
得到
{
返回所选产品;
}
设置
{//RaisePropertyChanged和广播类型为PropertyChangedMessage的消息
设置(“SelectedProduct”,参考SelectedProduct,值,真);
}
}
公共产品视图模型(IDataService数据服务)
{
this.dataService=dataService;
Products=dataService.GetAllProducts();
}
}
公共类详细信息viewmodel:ViewModelBase
{
私人资料;
公开详情
{
得到
{
退货详情;
}
设置
{//RaisePropertyChanged
设置(“详细信息”、参考详细信息、值);
}
}
公共细节视图模型(IDataService数据服务)
{
this.dataService=dataService;
Register(this,m=>Details=dataService.GetDetails(m.NewValue.Model.ProductID));
}
}
现在可以了,但在选择产品后,所有详细信息都会立即在所有详细信息选项卡中获取。
我一直在想,也许当用户单击MainView中的选项卡时,MainViewModel应该向ProductviewModel发送一条带有选项卡索引的消息,然后ProductviewModel应该发送另一条消息,根据选项卡索引将SelectedProduct传递给当前请求的选项卡项的DetailsViewModel,这将更新其详细数据
但是,我如何根据选项卡索引(而不是所有选项卡索引)只向当前请求的tabitem/DetailsView发送消息
而且这种往返听起来太复杂了。你能给我一些建议吗?
还是完全错了?
也许还有另一种更简单、更优雅的解决方案?我想你想要的是经典的酒吧/酒吧模式。当用户单击选项卡控件项时,将引发名为RequestViewOfProductDetails的事件。您可以使用以下内容在主视图模型中设置发布:
public MasterViewModel()
{
Messenger.Default.Send<RequestViewOfProductDetails>(_selectedProduct);
}
public主视图模型()
{
Messenger.Default.Send(_selectedProduct);
}
然后,在详细信息视图模型中,设置视图模型以响应该事件:
Messenger.Default.Register<RequestViewOfProductDetails>(this, delegate(Product prod)
{
// fetch details
});
Messenger.Default.Register(此,委托(产品生产)
{
//获取详细信息
});
您将为每个详细信息类型设置消息,在每个选项卡项的选择上发布特定的详细信息事件。我知道这很乏味,但这会把所有标签分开。如果是我,我会做一些不同的事情。我会在后台工作线程上执行请求,这样您就可以避免针对特定选项卡的头痛了。一旦选择了一个产品,只需分派getter以异步方式填充所有选项卡,事情就会透明地发生 我想你想要的是经典的酒吧/酒吧模式。当用户单击选项卡控件项时,将引发名为RequestViewOfProductDetails的事件。您可以使用以下内容在主视图模型中设置发布:
public MasterViewModel()
{
Messenger.Default.Send<RequestViewOfProductDetails>(_selectedProduct);
}
public主视图模型()
{
Messenger.Default.Send(_selectedProduct);
}
然后,在详细信息视图模型中,设置视图模型以响应该事件:
Messenger.Default.Register<RequestViewOfProductDetails>(this, delegate(Product prod)
{
// fetch details
});
Messenger.Default.Register(此,委托(产品生产)
{
//获取详细信息
});
您将为每个详细信息类型设置消息,在每个选项卡项的选择上发布特定的详细信息事件。我知道这很乏味,但这会把所有标签分开。如果是我,我会做一些不同的事情。我会在后台工作线程上执行请求,这样您就可以避免针对特定选项卡的头痛了。一旦选择了一个产品,只需分派getter以异步方式填充所有选项卡,事情就会透明地发生 通常,我会让我的
视图模型
跟踪选项卡
和SelectedTab
,并在SelectedTab
属性更改事件中加载当前选项卡
大概是这样的:
public MasterViewModel()
{
Messenger.Default.Send<RequestViewOfProductDetails>(_selectedProduct);
}
//不使用属性更改将其扩展为完整属性
//为简单起见,此处提供通知
可观察采集标签;
选择ViewModelBase选项卡;
void MyViewModel_PropertyChanged(对象发送方,PropertyChangedEventArgs e)
{
如果(如PropertyName==“SelectedTab”)
{
如果(所选选项卡为IDetailsTab)
((IDetailsTab)SelectedTab)。加载产品(SelectedProduct);
//或者根据您的结构:
var productsTab=Tabs[0]作为ProductsViewModel;
((IDetailsTab)SelectedTab)。加载产品(productsTab.SelectedProduct);
}
}
您的XAML将如下所示:
典型