Условные шаблоны данных при привязке к коллекции - PullRequest
1 голос
/ 01 декабря 2011

Пример применения:

Пример приложения, к которому относится предоставленный код, отображает список Vehicle объектов через Binding. Класс Vehicle является классом верхнего уровня, который может быть получен подклассами, например. Car и Bike. Пример приложения на данный момент отображает имя владельца Vehicle.

Пример кода модели:

public class Vehicle
{
    private string _ownerName;
    public string ownerName
    {
        get { return _ownerName; }
        set { _ownerName = value; }
    }
}

public class Car : Vehicle
{
    public int doors;
}

public class Bike : Vehicle
{
    // <insert variables unique to a bike, ( I could not think of any...)>
}

UserControl XAML код:

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="itemTemplate">
            <WrapPanel>
                <TextBlock Text="{Binding Path=ownerName}"/>
            </WrapPanel>
        </DataTemplate>
    </Grid.Resources>
    <ListBox x:Name="list" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5" ItemsSource="{Binding}" ItemTemplate="{StaticResource itemTemplate}" />
</Grid>

Код UserControl позади:

    public List<Vehicle> vehicleList = new List<Vehicle>();

    public CustomControl()
    {
        InitializeComponent();
        createSomeVehicles();
        list.DataContext = vehicleList;
    }

    public void createSomeVehicles()
    {
        Car newcar = new Car();
        newcar.doors = 5;
        newcar.ownerName = "mike";

        Bike newbike = new Bike();
        newbike.ownerName = "dave";

        vehicleList.Add(newcar);
        vehicleList.Add(newbike);
    }

Что я хочу сделать:

Я хотел бы иметь возможность отображать кнопку в списке объектов в зависимости от типа объекта Vehicle. Например. Я хотел бы отобразить кнопку Open Boot в элементе списка для Car; Тип Bike не имеет начальной загрузки, поэтому ни одна кнопка не будет отображаться в элементе списка.

Идея о том, как этого добиться:

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

object.Template = (ControlTemplate)control.Resources["templateForCar"];

Проблема здесь в том, что я использую Binding для всего списка, и поэтому нет способа вручную связать DataTemplate с каждым из элементов списка, привязка списка управляет DataTemplate его элементов.

1 Ответ

5 голосов
/ 01 декабря 2011

Вы можете создать шаблон данных для каждого мотоцикла и автомобиля (и для любого типа CLR). Указав свойство DataTemplate DataType, шаблон будет автоматически применяться всякий раз, когда WPF видит этот тип.

<Grid>
    <Grid.Resources>
        <DataTemplate DataType="{x:Type local:Car}">
            <WrapPanel>
                <TextBlock Text="{Binding Path=ownerName}"/>
                <Button Content="Open Boot" ... />
            </WrapPanel>
        </DataTemplate>
        <DataTemplate DataType="{x:Type local:Bike}">
            <WrapPanel>
                <TextBlock Text="{Binding Path=ownerName}"/>
            </WrapPanel>
        </DataTemplate>
    </Grid.Resources>
    <ListBox x:Name="list" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5" ItemsSource="{Binding}" />
</Grid>
...