【发布时间】:2018-11-15 21:26:21
【问题描述】:
我目前正在使用 WPF 应用程序并且有几个问题。到目前为止,我一直将所有业务逻辑放在一个 ViewModel 中,现在我注意到 ViewModel 没有特定的上下文。
一个例子是:
<telerik:RadSplitContainer Orientation="Vertical" telerik:DockingPanel.InitialSize="750,200">
<telerik:RadPaneGroup IsContentPreserved="False" telerik:ProportionalStackPanel.RelativeSize="200,300" >
<telerik:RadPane
<ContentControl ContentTemplate="{StaticResource CategoryTemplate}"
Content="{Binding CategoryViewModel}" />
</telerik:RadPane>
</telerik:RadPaneGroup>
<telerik:RadPaneGroup IsContentPreserved="False" telerik:ProportionalStackPanel.RelativeSize="100,120">
<telerik:RadPane Header="Items list"
CanUserClose="False" CanUserPin="False"
CanDockInDocumentHost="True">
<ContentControl ContentTemplate="{StaticResource ItemsListTemplate}"
Content="{Binding ItemsViewModel}" />
</telerik:RadPane>
</telerik:RadPaneGroup>
</telerik:RadSplitContainer>
然而,这就是 mainwindows.xaml 的样子,它是由多个视图构建的,这些视图被指定为一个数据模板。此时我决定从庞大的通用视图模型中提取业务逻辑,并为每个视图创建一个视图模型。
我有两个视图,一个用于类别,一个用于与类别对应的项目。这两个视图包含一个gridview,它显示CategoryView中的类别和与该类别对应的Items。
包含所有项目的视图模型最初是空的,类别只是从数据库中检索所有现有类别。我在 CategoryViewModel 中还有一个 SelectedCategory,其中包含我选择的网格行项目。
我想做的是在 categoryView 的网格中选择一行,我希望 CategoryViewModel 告诉 ItemsViewModel 检索与我从 CategoryViewModel 检索的 categoryID 对应的项目。然后用 INotifyPropertychanged 刷新 itemsViewModel 中的 itemscollection 并刷新网格上的视图。
我的 mainView 视图和视图模型:
public MainViewModel()
{
this.InitializeCommands();
this.ItemsViewModel = new ItemsViewModel();
this.CategoryViewModel = new CategoryViewModel();
}
public ViewModelBase CategoryViewModel
{
get { return this._categoryViewModel; }
set
{
if (this._categoryViewModel != value)
{
this._categoryViewModel = value;
}
}
}
public ViewModelBase ItemsViewModel
{
get
{
if (this._itemsViewModel == null)
{
this._itemsViewModel;
}
return this._itemsViewModel;
}
set
{
if (this._itemsViewModel != value)
{
this._itemsViewModel = value;
}
}
}
在 MainView 中使用的另一个视图数据模板的示例:
<DataTemplate x:Key="NewsTemplate">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<telerik:RadBusyIndicator x:Name="BusyIndicator">
<telerik:RadGridView Name="gridView"
ItemsSource="{Binding
Category}"
SelectedItem="{Binding SelectedCategory, Mode=TwoWay}">
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn DataMemberBinding={Binding Name}" Header="Name"/>
</telerik:RadGridView>
</telerik:RadBusyIndicator>
</Grid>
</DataTemplate>`
为项目添加了视图模型:
public ObservableCollection<Item> GetItems
{
get
{
this._getItems = GetFromDb.GetItems(CategoryID)
return this._getItems;
}
set
{
if (this._getItems != value)
{
this._getItems = value;
this.OnPropertyChanged("GetItems");
}
}
}
public QueryableCollectionView Items
{
get
{
return this._items = new QueryableCollectionView(GetItems(CategoryID));
}
set
{
if (this._items != value)
{
this._items = value;
this.OnPropertyChanged(() => Items);
}
}
}
MainViewModel(如果你看一下,我有一个方法 GetFromDb.GetItems(CategoryID) 可以检索项目):
public MainViewModel()
{
this.InitializeCommands();
this.CategoryViewModel = new CategoryViewModel();
this.ItemsViewModel = new ItemsViewModel();
this.CategoryViewModel.OnChanged += (s, e) => {
//this one?
this.ItemsViewModel.ContractMetaDatas(CategoryViewModel.ID)
//this one?
this.ItemsViewModel.ContractMetaDatas = new QueryableCollectionView(GetFromDb.GetItems(CategoryID));
};
}
我怎样才能做到这一点?
【问题讨论】:
-
您是否每页使用 1 个视图模型?
-
嗨@Stefan。是的,我在每个视图/页面或更确切地说是组件使用视图模型。我得到了一个 1000x1000 的网格,我将它分成了几个包含不同视图/视图资源的区域。这是一个单页应用程序,同一页面上有许多视图。
-
好的;假设您在某种容器中拥有这些视图模型:在 CategoryViewModel 中定义 categoryID 已更改的事件(您可以为此使用 INotifyPropertyChanged 事件,但这并不理想)。在您的容器中捕获它并将其传递给 ItemsViewModel。