У меня есть UserControl
ParentView, содержащий DataGrid
и catel:TabControl
, в котором каждый TabItem
крошечное UserControl
и чей ViewModel является подкласс BaseTabViewModel.Получить свойство ViewModel TabItem, когда он выбран
Этот BaseTabViewModel
содержит ObservableCollection
пользовательского класса, свойства которого будут генерировать столбцы DataGrid
.
Поскольку у меня есть только один DataGrid для всех вкладок, как я могу автоматически его заполнить с помощью ObservableCollection выбранной модели просмотра tab?
Прямо сейчас, я просто выгружать вкладки (LoadTabItems="SingleUnloadOthers"
) и, так как ViewModel каждой вкладки регенерировать свою коллекцию, когда инстанциирован, я использую InterestedIn и OnViewModelPropertyChanged, чтобы получить его; но это разгрузочное поведение не является полностью надежным, и я часто оказываюсь с DataGrid, который по-прежнему заполняется предыдущей вкладкой, а не очищается при изменении вкладки.
Следует отметить, что тот факт, что он очищается, не является желательным поведением, у меня просто нет другого выбора прямо сейчас. Каждая загруженная табуляция - моя цель.
Я знаю, что наследование довольно нахмурилось, когда дело доходит до viewmodels, но я, честно говоря, не могу придумать лучшего способа сделать это.
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 нет ничего интересного, так как они не взаимодействуют со своим родителем, за исключением некоторых свойств [ViewModelToModel]
.
Ничего себе. Наверное, я устал не думать об этом. Тем не менее я не знаю, как я могу определить модель просмотра для ребенка, которая была выбрана ... Но я на самом деле пытаюсь что-то сделать так, чтобы дети BaseTabViewModel находились в свойстве коллекции внутри ParentViewModel и динамически создавали TabItems из этой коллекции ... Я полагаю, что это вложенные viewmodels. – Kilazur
Если вы используете поведение вкладок «UnloadOthers», вы можете изменить выбор в методе Initialize моделей просмотра. –
Я согласен с вашим ответом, но это не соответствует моей проблеме. У меня довольно сложная система унаследованных классов, и я решил решить несколько вложенных режимов просмотра. Он чище и проще в обслуживании и отладке, вместо того, чтобы следить за связью OnViewModelPropertyChanged и позволяет мне динамически создавать представления (благодаря ViewModelToModelConverter). – Kilazur