私は既知のインターフェイスのコレクションで初期化されたDataTemplateSelectorを作成しました。セレクタに渡された項目がこれらのインタフェースのいずれかを実装する場合、関連するデータテンプレートが返されます。DataTemplateがDataTemplateSelectorから明示的に返されたときに、DataTemplateをインターフェイスにバインドできないのはなぜですか?
まず、ここで問題になっているICategoryインタフェースは
が...public interface ICategory
{
ICategory ParentCategory { get; set; }
string Name { get; set; }
ICategoryCollection Subcategories { get; }
}
はここで、基本クラスやインターフェイスだけではなく、特定の具体的なクラスに基づいて一致DataTemplateSelectorだ...だ
[ContentProperty("BaseTypeMappings")]
public class SubclassedTypeTemplateSelector : DataTemplateSelector
{
private delegate object TryFindResourceDelegate(object key);
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var frameworkElement = container as FrameworkElement;
foreach(var baseTypeMapping in BaseTypeMappings)
{
// Check if the item is an instance of, a subclass of,
// or implements the interface specified in BaseType
if(baseTypeMapping.BaseType.IsInstanceOfType(item))
{
// Create a key based on the BaseType, (not item.DataType as usual)
var resourceKey = new DataTemplateKey(baseTypeMapping.BaseType);
// Get TryFindResource method from either the FrameworkElement,
// or from the application
var tryFindResource = (frameworkElement != null)
? (TryFindResourceDelegate)frameworkElement.TryFindResource
: Application.Current.TryFindResource;
// Use the TryFindResource delegate from above to try finding
// the resource based on the resource key
var dataTemplate = (DataTemplate)tryFindResource(resourceKey);
dataTemplate.DataType = item.GetType();
if(dataTemplate != null)
return dataTemplate;
}
}
var defaultTemplate = DefaultDataTemplate ?? base.SelectTemplate(item, container);
return defaultTemplate;
}
public DataTemplate DefaultDataTemplate { get; set; }
public Collection<BaseTypeMapping> BaseTypeMappings { get; } = new Collection<BaseTypeMapping>();
}
public class BaseTypeMapping
{
public Type BaseType { get; set; }
}
DataType = ICategoryを持つそれぞれのHierarchicalDataTemplateと共にリソースにどのようにセットアップされているのですか?
<HierarchicalDataTemplate DataType="{x:Type model:ICategory}"
ItemsSource="{Binding Subcategories}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
<is:SubclassedTypeTemplateSelector x:Key="SubclassedTypeTemplateSelector">
<!--<is:BaseTypeMapping BaseType="{x:Type model:ICategory}" />-->
</is:SubclassedTypeTemplateSelector>
両方のステップ実行、予想通り
そして最後に、ここでそれを使用してツリービューが...
<TreeView x:Name="MainTreeView"
ItemsSource="{Binding Categories}"
ItemTemplateSelector="{StaticResource SubclassedTypeTemplateSelector}" />
だ、私はそれをデバッグしてきましたし、が正しいデータテンプレートを確認することができ、ツリービューにを返されていますであるため、TreeViewは、ItemSourceバインディングとしてサブクエリを正しくロードしています。 HierarchicalDataTemplateにあります。これらはすべて期待通りに機能します。
テンプレートの内容自体は機能しません。ご覧のように、テンプレートは単にカテゴリの名前を表示することになっていますが、テンプレートなしでContentPresenterに直接配置されているかのようにオブジェクトをそのまま表示しているだけです。 UIで表示されるのはToStringの結果だけです。テンプレートの内容は完全に無視されます。
私が考えることができるのは、データ型用のインターフェイスを使用しているために機能しないことだけですが、子どものItemsSourceのバインディングが機能するため、ここでは困惑しています。
メモ:テストとして、コンクリートタイプ(カテゴリのみでなくカテゴリ)に基づいて2番目のDataTemplateを作成しました。これを実行すると、期待通りに機能しました。問題は、具体的な型がUIで参照されていないアセンブリにあることです。これが最初にインターフェイスを使用している理由のすべてです。
注:DataTypeプロパティを設定する代わりに、キーを使用してテンプレートを検索する方法も変更してみました。その場合、前と同じセレクタが同じリソースを見つけますが、まだ動作しません。
皮肉なことしかし、私は同じ鍵が、結合StaticResource経由で直接TreeViewコントロールのItemTemplateに設定することを使用する場合、それない仕事、私はセレクタからテンプレートを返すときにのみ動作していないという意味といは、DataTypeが設定されているかどうかに関係なく表示されます。*
短い答え:それはそのように設計されているためです。おそらく、あなたは単一のクラスに対して複数の一致を得ることができるからです。 [MSDNの公式回答](https://social.msdn.microsoft.com/Forums/vstudio/en-US/1e774a24-0deb-4acd-a719-32abd847041d/data-templates-and-interfaces?forum=wpf) –
あなたのMSDNリンクを見れば、あなたは、私が上でやっているDataTemplateSelectorを使うことができると具体的に言われます。あなたの主張と、彼らが決定したことは、インタフェース自体にマッチさせようとしていることです。これは私がここで達成しようとしているものではありません。 – MarqueIV
元の質問は「なぜDataTemplateをインターフェイスにバインドできないのですか?」でした。私はあなたがなぜそれがそうであるかに興味があると思った。 –