好吧,使用 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>
这个item模板使用ModelView的其他视图来渲染item。ModelView展示了公共信息,具体的模型数据由ModelSelector选择的view展示。
<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,而另一个参数(Container)的dataContext为null。我无法知道ModelViewModel的值是什么来选择正确的视图。
如果我将数据模板放在 ListView 项目模板中,则该项目具有 ModelViewMode 的值,但我需要将该模板放在单独的文件中,因为它将用于应用程序的不同部分。
我不知道我可以访问 ModelSelector 中的 ModelViewModel 吗?