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.
This BaseTabViewModel
contains a ObservableCollection
of a custom class, whose properties will generate the columns of the DataGrid
.
Since I have only one DataGrid for all tabs, how can I fill it with the ObservableCollection of selected tab's viewmodel automatically?
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.
I know inheritance is pretty frowned upon when it comes to viewmodels, but I honestly can't think of a better way to do it.
ParentView
<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>
ParentViewModel
[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's childs have nothing of interest, as they don't interact with their parent, except for some [ViewModelToModel]
properties.