Выбор шаблона на основе данных в WPF - PullRequest
2 голосов
/ 29 июня 2009

У меня есть простой пример XAML:

<Window x:Class="DynTemplateTest.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="ItemTemplate">
            <ItemsControl ItemsSource="{Binding}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Rectangle Width="30" Height="30" Fill="Red"></Rectangle>                        
                    </DataTemplate>
                </ItemsControl.ItemTemplate>  
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemContainerStyle>
                    <Style>
                        <Setter Property="Canvas.Left" Value="{Binding Position}"></Setter>
                    </Style>
                </ItemsControl.ItemContainerStyle>
            </ItemsControl>
        </DataTemplate>
    </Window.Resources>

    <DockPanel LastChildFill="True">
        <ContentPresenter
            Content="{Binding Path=Items}"
            ContentTemplate="{StaticResource ItemTemplate}"
            >
        </ContentPresenter>
    </DockPanel>

</Window>

Рендеринг моих предметов в наблюдаемой коллекции в стиле MVVM. Каждый элемент имеет свое горизонтальное положение в свойстве. Каждый элемент также имеет свойство IsSpecial, которое сообщает, хочет ли оно быть отображено особым образом. Я хочу, чтобы обычные элементы (IsSpecial = false) отображались в виде красных квадратов (уже в коде), а специальные элементы - в виде синих кружков с «специальным» текстом внутри.

Что я не знаю, так это как настроить код XAML для выбора шаблонов элементов. Есть ли способ сделать это без кодирования моего собственного ItemTemplateSelector? Будет ли все еще работать с позиционированием холста на основе привязки. Я думаю, что решение состоит в том, чтобы извлечь шаблон элемента в отдельный шаблон, создать еще один шаблон для специальных элементов и затем каким-то образом поиграть с триггерами ... но для меня это не очень легко, так как я новичок в WPF на данный момент.

Другое дело, что мне не нравится, как Позиция передается предметам. Есть ли другой способ?

Есть ли другие рекомендации, как улучшить код?

1 Ответ

5 голосов
/ 30 июня 2009

Я сам решил: D

<Window x:Class="DynTemplateTest.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="NormalItem">
            <Rectangle Width="30" Height="30" Fill="Red"></Rectangle>                        
        </DataTemplate>
        <DataTemplate x:Key="SpecialItem">
            <Rectangle Width="30" Height="30" Fill="Red"></Rectangle>                        
        </DataTemplate>
        <DataTemplate x:Key="ItemTemplate">
            <ItemsControl ItemsSource="{Binding}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <ContentControl Content="{Binding}" ContentTemplate="{StaticResource NormalItem}" x:Name="ItemsContentControl" />
                        <DataTemplate.Triggers>
                            <DataTrigger Binding="{Binding Path=IsSpecial}" Value="true">
                                <Setter TargetName="ItemsContentControl" Property="ContentTemplate" Value="{StaticResource SpecialItem}" />
                            </DataTrigger>
                        </DataTemplate.Triggers>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>  
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemContainerStyle>
                    <Style>
                        <Setter Property="Canvas.Left" Value="{Binding Position}" />
                    </Style>
                </ItemsControl.ItemContainerStyle>
            </ItemsControl>
        </DataTemplate>
    </Window.Resources>

    <DockPanel LastChildFill="True">
        <ContentPresenter
            Content="{Binding Path=Items}"
            ContentTemplate="{StaticResource ItemTemplate}"
            >
        </ContentPresenter>
    </DockPanel>

</Window>

Но все же, есть мысли об альтернативах или улучшениях?

...