2017-04-14 6 views
1

ComboBoxコントロールのカスタムDataTemplateSelectorを作成しています。これを使用して、異なる種類のオブジェクトに対して異なるDateTemplatesを表示する必要がありますComboBoxのクローズドモードとオープンモード。カスタムDataTemplateSelectorのC#でDataTemplateを取得する方法

ここに私が思い付いたDataTemplateSelectorです:

public class ComboBoxTypedDataTemplateSelector : DataTemplateSelector 
{ 
    public IEnumerable<DataTemplate> SelectedTemplates { get; set; } 

    public IEnumerable<DataTemplate> DropDownTemplates { get; set; } 

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) 
    { 
     IEnumerable<DataTemplate> source = container.FindParent<ComboBoxItem>() == null 
      ? SelectedTemplates // Get the template for the closed mode 
      : DropDownTemplates; // Get the template for the open UI mode 
     Type type = item.GetType(); 
     return null; // Some LINQ to get the first DataTemplate in source with the {x:DataType} that equals type 
    } 
} 

public sealed class DataTemplatesCollection : List<DataTemplate> { } 

そして、ここで私はXAMLでそれを使用したい方法は次のとおりです。

<ComboBox> 
    <mvvm:ComboBoxTypedDataTemplateSelector> 
     <mvvm:ComboBoxTypedDataTemplateSelector.SelectedTemplates> 
      <mvvm:DataTemplatesCollection> 
       <DataTemplate x:DataType="models:SomeType"> 
        <TextBlock Text="{x:Bind ...}"/> 
       </DataTemplate> 
       <DataTemplate x:DataType="models:SomeOtherType"> 
        <TextBlock Text="{x:Bind ...}"/> 
       </DataTemplate> 
      </mvvm:DataTemplatesCollection> 
     </mvvm:ComboBoxTypedDataTemplateSelector.SelectedTemplates> 
     <mvvm:ComboBoxTypedDataTemplateSelector.DropDownTemplates> 
      <mvvm:DataTemplatesCollection> 
       <DataTemplate x:DataType="models:SomeType"> 
        <TextBlock Text="{x:Bind ...}"/> 
       </DataTemplate> 
       <DataTemplate x:DataType="models:SomeOtherType"> 
        <TextBlock Text="{x:Bind ...}"/> 
       </DataTemplate> 
      </mvvm:DataTemplatesCollection> 
     </mvvm:ComboBoxTypedDataTemplateSelector.DropDownTemplates> 
    </mvvm:ComboBoxTypedDataTemplateSelector> 
</ComboBox> 

を今、私が欠けているパズルの唯一の作品、私はC#でその{x:DataType}プロパティを取得する方法を理解できません(実際には実際のプロパティではないことはわかっていますが、コードで取得する方法があることを願っています)。 右のテンプレートグループから、オブジェクトごとに右にDataTemplateを得るには、そのようなものが必要です。 これを実現する方法はありますか?

:私はちょうど、各項目タイプのために返すようにテンプレートのハードコーディングされた名前を持つ特定のDataTemplateSelectorを書くことができ知っている、と私はフォールバックオプションとして、そのメソッドを使用することができます。しかし、私は、これをモジュール化し、将来再利用できるようにするために、このアプローチでより汎用的なセレクタを書くことが可能かどうか疑問に思っていました。

ありがとうございました!

EDIT

public class DataTypeHelper 
{ 
    public static Type GetAttachedDataType(DataTemplate element) 
    { 
     return (Type)element.GetValue(AttachedDataTypeProperty); 
    } 

    public static void SetAttachedDataType(DataTemplate element, Type value) 
    { 
     element.SetValue(AttachedDataTypeProperty, value); 
    } 

    public static readonly DependencyProperty AttachedDataTypeProperty = 
     DependencyProperty.RegisterAttached("AttachedDataType", typeof(Type), typeof(DataTypeHelper), new PropertyMetadata(default(Type))); 
} 

そして、私はこのようにそれを使用することを試みた:ヴィンセントの提案以下、私はDataTemplate内の指定されたTypeを保存するために添付プロパティを書いた

... 
<DataTemplate x:DataType="someXlmns:SomeClass" 
       mvvm:DataTypeHelper.AttachedDataType="someXlmns:SomeClass"> 
    ... 
</DataTemplate> 

しかし、XamlParseExceptionという行が私の添付のプロパティを自分のタイプに設定しています。私はそのプロパティを "Grid"(テストと同様)に設定しようとしましたが、クラッシュしません。なぜ私のカスタムタイプで動作しないのかわかりません。

EDIT#2:x:Typeマークアップ拡張がUWPで使用できないようで、XAMLから直接Typeインスタンスを取得する別の方法は見つけられませんでしたので、XAMLでタイプ名を使用して、それをテンプレートセレクタのitem.GetType().Nameと比較するだけでした。

XAMLから直接Typeプロパティを割り当てる機能は、XAMLデザイナーでも構文/スペルチェックが行われているように優れていますが、少なくともこの方法はうまくいきます。

答えて

1

この値は取得できません。これはコンパイラがバインディングに適切なコードを生成できるようにするヒントです。

必要なものを格納するためにカスタムの添付プロパティを作成することも、Nameプロパティを使用することもできます。

セレクタの実装で次に

Template1.GetValue(FrameworkElement.NameProperty); 
+0

お寄せいただきありがとうございます。添付されたプロパティの実装で私の質問を更新しました。それを見てみることはできますか?私の状況でこの提案の仕事を得るために管理しているのは、これを答えとしてマークします。 – Sergio0694

+0

Nevermind、UWPのXAMLからTypeプロパティを割り当てることができないので、テンプレートセレクタの型名と比較する文字列を使用しました(更新された質問を参照)。再度、感謝します! – Sergio0694

0

ここではデータの種類に応じて異なるのDataTemplateを使用して、私が見つけたサンプルです。コード:

public class MyDataTemplateSelector : DataTemplateSelector 
{ 
    public Dictionary<Type, DataTemplate> TemplateDictionary { get; set; } 
    protected override DataTemplate SelectTemplateCore(object item) 
    { 
     // select datatemplate depending on item type 
     Type itemType = item.GetType(); 
     if (!TemplateDictionary.Keys.Contains(itemType)) 
     { 
      return null; 
     } 
     return TemplateDictionary[itemType]; 
    } 
    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) 
    { 
     // select datatemplate depending on item type 
     Type itemType = item.GetType(); 
     if (!TemplateDictionary.Keys.Contains(itemType)) 
     { 
      return null; 
     } 
     return TemplateDictionary[itemType]; 
    } 
} 

ここにリンクhttps://code.msdn.microsoft.com/How-to-bind-data-to-04dcf26dがあります。ソースコードをダウンロードすることができます。

関連する問題