问题描述
我有一个 UserControl
ParentView 包含一个 DataGrid
和一个 catel:TabControl
,其中每个 TabItem
是一个很小的 UserControl
,它的 ViewModel 是 BaseTabViewModel 的 子类.
I have a UserControl
ParentView containing a DataGrid
and a catel:TabControl
, in which each TabItem
is a tiny UserControl
and whose ViewModel is a subclass of a BaseTabViewModel.
此BaseTabViewModel
包含一个自定义类的ObservableCollection
,其属性将生成DataGrid
的列.
This BaseTabViewModel
contains a ObservableCollection
of a custom class, whose properties will generate the columns of the DataGrid
.
由于所有选项卡只有一个 DataGrid,我如何使用所选选项卡的视图模型的 ObservableCollection 自动填充它?
现在,我只是卸载选项卡 (LoadTabItems="SingleUnloadOthers"
),并且由于每个选项卡的视图模型在实例化时都会重新生成其集合,因此我使用了 InterestedIn 和 OnViewModelPropertyChanged 来获取它;但是这种卸载行为并不完全可靠,我经常发现自己的 DataGrid 仍然由前一个选项卡填充,而不是在更改选项卡时被清除.
Right now, I just unload tabs (LoadTabItems="SingleUnloadOthers"
) and, since every tab's viewmodel regenerate its collection when instanciated, I use InterestedIn and OnViewModelPropertyChanged to get it; yet this unloading behavior isn't completely reliable, and I often find myself with the DataGrid still filled by the previous tab instead of being cleaned when changing tab.
需要注意的是,它被清理并不是一种理想的行为,我现在别无选择.让每个标签保持加载状态是我的目标.
To note, the fact that it gets cleaned isn't a desired behavior, I just have no other choice right now. Having each tab remaining loaded is my goal.
我知道当涉及到视图模型时,继承是很不受欢迎的,但老实说,我想不出更好的方法来做到这一点.
父视图
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<catel:TabControl LoadTabItems="SingleUnloadOthers">
<TabItem Header="FIRST">
<local:FirstView/>
</TabItem>
<TabItem Header="SECOND">
<local:SecondView/>
</TabItem>
<TabItem Header="THIRD">
<local:ThirdView/>
</TabItem>
<TabItem Header="FOURTH">
<local:FourthView/>
</TabItem>
</catel:TabControl>
<DataGrid Grid.Row="1" IsReadOnly="True" ItemsSource="{Binding Fields}"/>
</Grid>
父视图模型
[InterestedIn(typeof(FirstViewModel))]
[InterestedIn(typeof(SecondViewModel))]
[InterestedIn(typeof(ThirdViewModel))]
[InterestedIn(typeof(FourthViewModel))]
public class ParentViewModel : ViewModelBase
{
public ObservableCollection<Field> Fields
{
get { return GetValue<ObservableCollection<Field>>(FieldsProperty); }
set { SetValue(FieldsProperty, value); }
}
public static readonly PropertyData FieldsProperty = RegisterProperty("Fields", typeof(ObservableCollection<Field>));
protected override void OnViewModelPropertyChanged(IViewModel viewModel, string propertyName)
{
if (propertyName.Equals("Fields"))
{
BaseParserViewModel p = viewModel as BaseParserViewModel;
Fields = p != null ?? p.Fields;
}
base.OnViewModelPropertyChanged(viewModel, propertyName);
}
}
BaseTabViewModel
public abstract class BaseTabViewModel : ViewModelBase
{
protected BaseParserViewModel()
{
Fields = new ObservableCollection<Field>();
}
public ObservableCollection<Field> Fields
{
get { return GetValue<ObservableCollection<Field>>(FieldsProperty); }
set { SetValue(FieldsProperty, value); }
public static readonly PropertyData FieldsProperty = RegisterProperty("Fields", typeof(ObservableCollection<MappedField>));
}
BaseTabViewModel 的子项没有任何兴趣,因为除了某些 [ViewModelToModel]
属性之外,它们不与父项交互.
BaseTabViewModel's childs have nothing of interest, as they don't interact with their parent, except for some [ViewModelToModel]
properties.
推荐答案
如果你需要跨多个视图模型管理状态,我总是建议引入一个服务.视图模型可以存活很短或很长一段时间,但视图模型之间最好的通信仍然是保持状态的服务(即使虚拟机已经消失).
If you need to manage state across several view models, I always recommend introducing a service. A view model is something that can live for a short or long amount of time, but the best communication between view models is still services that hold the state (even when the vm's are gone).
以下是我的交流偏好:
- 服务(最佳方式,允许完全控制,最佳性能)
- 基于属性的通信
- 消息传递(MessageMediator)
我知道很多人都用 3 解决了他们的架构问题,但这是一个黑客,而不是一个可靠的解决方案.只需实现一个服务(注入所有虚拟机),如下所示:
I know a lot of people fix their architectural issues with 3, but it's a hack, not a solid solution. Just implement a service (that gets injected into all vm's) like this:
public class FieldCollectionManagementService : IFieldCollectionManagementService
{
private ObservableCollection<Field> _selectedCollection;
public ObservableCollection<Field> SelectedCollection
{
get { return _selectedCollection; }
set
{
_selectedCollection = value;
SelectedCollectionChanged.SafeInvoke(this);
}
}
public event EventHandler<EventArgs> SelectedCollectionChanged;
}
现在您无需属性即可轻松处理所有更改.然后你甚至可以在所有视图模型都消失后恢复状态.
Now you can easily handle all the changes without needing the attributes. Then you can even restore state when all view models are gone.
这篇关于选择选项卡时获取它的视图模型的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!