dataTemplateSelector を使用して、列挙値に基づいてビュー モデルに適したデータ テンプレートを選択するのに少し問題があります。
これは問題を再現するデモです。
ビューモデルで使用されるモデルの階層があります
モデル タイプを定義する列挙型は次のとおりです。
public enum ModelType
{
ModelA,
ModelB
}
モデルの基本クラスは次のとおりです。
public abstract class ModelBase
{
protected ModelBase(ModelType modelType)
{
ModelType = modelType;
}
public ModelType ModelType { get; private set; }
public string Name { get; set; }
}
子モデル クラスは次のとおりです。
public class ModelA:ModelBase
{
public ModelA():base(ModelType.ModelA)
{
Name = "ModelA";
}
public string PropertyModelA { get { return "PropertyModelA"; } }
}
と
public class ModelB : ModelBase
{
public ModelB()
: base(ModelType.ModelB)
{
Name = "ModelB";
}
public string PropertyModelB { get { return "PropertyModelB"; } }
}
私の MainViewModel と ModelViewModel はそれぞれ次のとおりです。
public class MainWindowViewModel:ViewModelBase
{
public MainWindowViewModel()
{
Models = new ObservableCollection<ModelViewModel>();
LoadModels();
}
public ObservableCollection<ModelViewModel> Models { get; private set; }
private void LoadModels()
{
Models.Add(new ModelViewModel(new ModelA()));
Models.Add(new ModelViewModel(new ModelB()));
Models.Add(new ModelViewModel(new ModelB()));
}
と
public class ModelViewModel : ViewModelBase
{
private ModelBase _model;
public ModelViewModel(ModelBase model)
{
_model = model;
}
public ModelBase Model
{
get { return _model; }
set
{
if (!_model.Equals(value))
{
_model = value;
OnPropertyChanged("Model");
}
}
}
}
その後、MainView に項目テンプレートを使用して各項目を表示するリスト ボックスがあります。
<ListBox x:Name="entryList" ItemsSource="{Binding Models}" >
<ListBox.ItemTemplate>
<DataTemplate>
<views:ModelView/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
このアイテム テンプレートは、ModelView と呼ばれる別のビューを使用してアイテムをレンダリングします。ModelView は共通情報を示し、特定のモデル データは ModelSelector によって選択されたビューによって示されます。
<UserControl.Resources>
<ResourceDictionary>
<selectors:ModelSelector x:Key="modelSelector" />
</ResourceDictionary>
</UserControl.Resources>
<StackPanel>
<TextBlock Text="{Binding Model.Name}" />
<ContentPresenter ContentTemplateSelector="{StaticResource modelSelector}" DataContext="{Binding }" />
</StackPanel>
現時点で、モデル セレクターによって選択できるビューは A と B です。
<StackPanel>
<TextBlock Text="{Binding Model.PropertyModelA}" />
</StackPanel>
<StackPanel>
<TextBlock Text="{Binding Model.PropertyModelB}" />
</StackPanel>
モデル セレクターは次のとおりです。
public class ModelSelector:DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var viewModel = item as ModelViewModel;
var dataTemplate = default(DataTemplate);
if (viewModel != null)
{
switch (viewModel.Model.ModelType)
{
case NestedDataTemplateSelectorTest.Models.ModelType.ModelA:
dataTemplate = CreateDataTemplate<ModelAView>();
break;
case NestedDataTemplateSelectorTest.Models.ModelType.ModelB:
dataTemplate = CreateDataTemplate<ModelBView>();
break;
default:
dataTemplate = this.SelectTemplate(item, container);
break;
}
}
return dataTemplate;
}
private DataTemplate CreateDataTemplate<TView>()
{
var dataTemplate = new DataTemplate();
var frameworkElement = new FrameworkElementFactory(typeof(TView));
dataTemplate.VisualTree = frameworkElement;
return dataTemplate;
}
}
問題は、DataTemplateSelector のパラメーター項目が null であり、他のパラメーター (コンテナー) の dataContext が null であることです。適切なビューを選択するための ModelViewModel の値を知る方法がありません。
データ テンプレートを ListView アイテム テンプレートに配置すると、アイテムには ModelViewMode の値が含まれますが、そのテンプレートはアプリケーションのさまざまな部分で使用されるため、別のファイルに含める必要があります。
ModelSelector で ModelViewModel にアクセスする方法がわかりません。