Как вы можете включить автоматический выбор DataTemplate на основе типа данных, как вы можете с элементом управления элементами?

Мы пишем очень специализированную ItemsControl, которая на самом деле имеет три ContentPresenter на «строку», каждая из которых привязана к другому объекту (например, к сетке бедняка) вместо более распространенного, такого как ListBox.

Теперь с ListBox, если вы явно не укажете ни ItemTemplate, ни ItemTemplateSelector, похоже, есть какой-то внутренний селектор, который применяет шаблон исключительно на основе типа данных. Однако наши ContentPresenter их не ловят. Мы также пытались заменить их на ContentControl, но это тоже не сработало.

Теперь я знаю, что могу просто написать свой собственный DataTypeTemplateSelector, который делает это, но мне интересно, эта функциональность уже «запечена» где-то, считается, что она используется с таким количеством ItemsControl (ListBox, TreeView, ComboBox', DataGrid и т. д.) и согласно этой статье MSDN...

http://msdn.microsoft.com/en-us/library/ms742521.aspx

... это должно работать по умолчанию! Но опять же, это не так.

Вот наш (псевдо) код...

<UserControl.Resources>

    <!-- These all work when the relevant items are in a ListBox,
         but not with stand-alone ContentPresenters or ContentControls -->

    <DataTemplate DataType="local:SomeTypeA">
        <TextBlock Text="{Binding Converter={c:DataTypeNameConverter}}" Foreground="Blue" />
    </DataTemplate>

    <DataTemplate DataType="local::SomeTypeB">
        <TextBlock Text="{Binding Converter={c:DataTypeNameConverter}}" Foreground="Purple" />
    </DataTemplate>

    <DataTemplate DataType="local::SomeTypeC">
        <TextBlock Text="{Binding Converter={c:DataTypeNameConverter}}" Foreground="Purple" />
    </DataTemplate>

</UserControl.Resources>

<!-- These don't pick up the templates -->
<ContentControl Content="{Binding Field1}" />
<ContentPresenter Content="{Binding Field2}" />

<!-- This however does -->
<ListBox ItemsSource="{Binding AllItems}" 

Итак... кто-то хочет попробовать, почему бы и нет?


person Mark A. Donohoe    schedule 27.09.2011    source источник
comment
Я использовал DataTemplates с ContentControls много раз в прошлом без проблем. Можете ли вы опубликовать свой реальный код вместо псевдокода? И будет ли это работать, если вы установите DataType равным {x:Type local:SomeTypeA} вместо просто "local:SomeTypeA"?   -  person Rachel    schedule 27.09.2011
comment
Рэйчел, ты права. Он работает с расширением разметки x:Type по той причине, что H.B. указано ниже... MSFT в своей бесконечной мудрости считает, что свойство называемое «DataType» имеет тип Object, а не тип System.Type, поэтому в отличие от «TargetType» стиля для DataTemplate у вас есть использовать разметку.   -  person Mark A. Donohoe    schedule 28.09.2011


Ответы (1)


DataType, по какой-то безумной причине , имеет тип Object, DataTemplates, следовательно, имеет набор string в этом свойстве, если вы не используете x:Type.


Изменить: свойство является объектом по очень веской причине, поскольку всегда те, кто может (и умеет) читать, имеют явное преимущество:

Если шаблон предназначен для данных объекта, это свойство содержит имя типа объекта данных (в виде строки). Чтобы обратиться к имени типа класса, используйте расширение разметки x:Type. Если шаблон предназначен для данных XML, это свойство содержит имя элемента XML. Дополнительные сведения об указании пространства имен, отличного от используемого по умолчанию, для элемента XML см. в примечаниях к документации.

person H.B.    schedule 27.09.2011
comment
Ааааа! Вот почему! Я так привык опускать x:Type при указании TargetType в стилях (где я предполагаю, что он правильно установлен как тип Type), поэтому, опуская его и здесь, когда вы говорите, что тип Object (и вы правы ... WTFBBQ, MSFT?!) вместо этого он интерпретируется как простая строка и, следовательно, никогда не совпадает! Отличный улов, тем более что вы знаете «Почему!» (Я почти написал, что это не нужно, пока не увидел ваш ответ.) Интересно, следует ли сообщать об этом как об ошибке в MS! (Кроме того, эмпирическое правило: всегда используйте разметку! Нагляднее и сработало бы!) Еще раз передайте! - person Mark A. Donohoe; 28.09.2011