DataTemplateSelector中的项目为null [英] Item is null in DataTemplateSelector

查看:121
本文介绍了DataTemplateSelector中的项目为null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用dataTemplateSelector为我的视图模型基于枚举值选择正确的数据模板会有一个小问题。

Well a have a little problem using a dataTemplateSelector to choose the right datatemplate for my view model based in an enum value.

这是一个演示该问题的演示

This is a demo that reproduces the issue.

我有一个供我的viewModel使用的模型层次结构

I have a hierarchy of models that are used by my viewModels

定义模型类型的枚举是:

The enum that define the model types is:

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是:

My MainViewModel and the ModelViewModel respectively are:

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中有一个使用项目模板显示每个项目的列表框。

After that I have a List box in my MainView that use a item template to show each item.

 <ListBox x:Name="entryList" ItemsSource="{Binding Models}"  >
            <ListBox.ItemTemplate>
                <DataTemplate>                       
                      <views:ModelView/>     
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

此项目模板使用另一个称为ModelView的视图来呈现该项目。ModelView显示常用信息,具体模型数据由ModelSelector选择的视图显示。

This item template use other view called ModelView to render the item.ModelView shows the common information , the specific model data are showed by the view selected by the 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:

At the moment the views that could be selected by the model selector are A and 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的值。

The problem is that the parameter item in the DataTemplateSelector is null and the other parameter(Container) have the dataContext in null.I don't have way to know which is the value of the ModelViewModel to choose the right view.

如果我将数据模板放在ListView Item模板中,则该项目具有ModelViewMode的值,但我需要将该模板保存在单独的文件中,因为它将在应用程序的不同部分中使用。

if I put the data template in the ListView Item template then the item have the value of the ModelViewMode but I need to have that template in a separate file because it will be used in diferent parts of the application.

我不知道该怎么做才能在ModelSelector中访问ModelViewModel吗?

I dont know can i do to have access to the ModelViewModel in the ModelSelector?

推荐答案

是,您可以通过 DataTemplateSelector 访问ViewModel。您的错误是您设置了 DataContext 属性:

Yes, you can access your ViewModel throug DataTemplateSelector. Your mistake is that you set the DataContext property:

DataContext="{Binding}"

对于 ContentPresenter ,您应设置 Content 属性

Content="{Binding}"

如果这样做,重写方法中的对象 item 将为完全 Content 属性。

If you will do that, the object item inside the overriden method will be exactly Content property.

根据 msdn文章


如果设置了ContentPresenter的ContentTemplateSelector属性,则ContentPresenter将适当的DataTemplate应用于Content属性,并显示结果UIElement及其子元素(如果有)。

If the ContentTemplateSelector property on the ContentPresenter is set, the ContentPresenter applies the appropriate DataTemplate to the Content property and the resulting UIElement and its child elements, if any, are displayed.

请注意 ContentPresenter 逻辑以显示内容

这篇关于DataTemplateSelector中的项目为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆