Отображать несколько типов из одного списка в WPF ListBox?

Я относительно новичок в WPF, и похоже, что есть несколько способов сделать это, но я не могу получить ни один из тех, которые я пытался работать.

У меня есть ObservableCollection, который содержит два разных типа.

Я хочу привязать этот список к ListBox и отобразить различные DataTemplates для каждого встреченного типа. Я не могу понять, как автоматически переключать шаблоны данных на основе типа.

Я попытался использовать свойство DataType DataTemplate и попытался использовать ControlTemplates и DataTrigger, но безрезультатно, либо ничего не появляется, либо утверждает, что он не может найти мои типы...

Пример Попытка:

У меня есть только один шаблон данных, подключенный к ListBox прямо сейчас, но даже это не работает.

XAML:

<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
    <DataTemplate x:Key="PersonTemplate">
        <TextBlock Text="{Binding Path=Name}"></TextBlock>
    </DataTemplate>

    <DataTemplate x:Key="QuantityTemplate">
        <TextBlock Text="{Binding Path=Amount}"></TextBlock>
    </DataTemplate>

</Window.Resources>
<Grid>
    <DockPanel>
        <ListBox x:Name="MyListBox" Width="250" Height="250" 
ItemsSource="{Binding Path=ListToBind}"
ItemTemplate="{StaticResource PersonTemplate}"></ListBox>
    </DockPanel>
</Grid>
</Window>

Код за:

public class Person
{
    public string Name { get; set; }

    public Person(string name)
    {
        Name = name;
    }
}

public class Quantity
{
    public int Amount { get; set; }

    public Quantity(int amount)
    {
        Amount = amount;
    }
}

public partial class Window1 : Window
{
    ObservableCollection<object> ListToBind = new ObservableCollection<object>();

    public Window1()
    {
        InitializeComponent();

        ListToBind.Add(new Person("Name1"));
        ListToBind.Add(new Person("Name2"));
        ListToBind.Add(new Quantity(123));
        ListToBind.Add(new Person("Name3"));
        ListToBind.Add(new Person("Name4"));
        ListToBind.Add(new Quantity(456));
        ListToBind.Add(new Person("Name5"));
        ListToBind.Add(new Quantity(789));
    }
}

Ответ 1

Вы говорите, что "он утверждает, что не может найти мои типы". Это проблема, которую вы должны исправить.

Проблема, скорее всего, в том, что вы не создаете декларацию пространства имен в XAML, которая ссылается на пространство имен и сборки CLR. Вам нужно добавить что-то вроде этого в элементе верхнего уровня XAML:

xmlns:foo="clr-namespace:MyNamespaceName;assembly=MyAssemblyName"

Как только вы это сделаете, XAML будет знать, что что-либо с префиксом пространства имен XML foo на самом деле является классом в MyAssemblyName в пространстве имен MyNamespaceName.

Затем вы можете ссылаться на это пространство имен XML в разметке, которая создала DataTemplate:

<DataTemplate DataType="{foo:Person}">

Конечно, вы можете создать селектор шаблонов, но это добавит кусок крейта в ваше программное обеспечение, которое не обязательно должно быть там. Там место для выбора шаблонов в приложениях WPF, но это не так.

Ответ 2

Вы должны использовать DataTemplateSelector. См. здесь для примера.

Дополнительная информация о MSDN