5

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 にアクセスする方法がわかりません。

4

4 に答える 4

14

はい、 DataTemplateSelectorを介して ViewModel にアクセスできます。あなたの間違いは、DataContextプロパティを設定することです:

DataContext="{Binding}"

ContentPresenterの場合Content、代わりにプロパティを設定する必要があります

Content="{Binding}"

そうすればitem、オーバーライドされたメソッド内のオブジェクトは正確にContentプロパティになります。

msdnの記事によると:

ContentPresenter の ContentTemplateSelector プロパティが設定されている場合、ContentPresenter は適切な DataTemplate を Content プロパティに適用し、結果の UIElement とその子要素 ​​(存在する場合) が表示されます。

を表示するContentPresenterロジックに注意して くださいContent

于 2013-01-24T04:40:46.373 に答える