F.P
F.P

Reputation: 17831

Different DataTemplate depending on the enumeration value of a property

I want something similar to what was asked here - but, I need the templates to depend on the value of a property, which is an enum.

The class looks simlar to this:

class ResultBlock
{
    public string Name { get; set; }
    public BlockType Type { get; set; }
    public IList<ResultBlock> ChildBlocks { get; private set; }
}

Where BlockType has three different values, BLOCK, FILE, FOLDER - Now, I want to create a data template to present differently, depending on what value ResultBlock.Type has in the current object.

I tried doing this with DataType=, but that didn't work, obviously. I'm sure there is some way to do this very easily in XAML only.

<TreeView.Resources>
    <HierarchicalDataTemplate DataType="{x:Type docom:ResultBlock}" ItemsSource="{Binding ChildBlocks}">
        <StackPanel Orientation="Horizontal">
            <StackPanel.Resources>
                <DataTemplate DataType="{x:Type docom:BlockType.BLOCK}">
                    <TextBlock Text="BLOCK:{Binding Name}" />
                </DataTemplate>
            </StackPanel.Resources>
        </StackPanel>
    </HierarchicalDataTemplate>
</TreeView.Resources>

Upvotes: 2

Views: 4320

Answers (3)

brunnerh
brunnerh

Reputation: 184441

You can trigger on the property, e.g.:

<HierarchicalDataTemplate DataType="{x:Type docom:ResultBlock}"
                          ItemsSource="{Binding ChildBlocks}">
    <ContentControl Content="{Binding}">
        <ContentControl.Style>
            <Style TargetType="ContentControl">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding BlockType}" Value="BLOCK"> 
                        <Setter Property="ContentTemplate">
                            <Setter.Value>
                                <DataTemplate>
                                     <!-- Data template for BLOCK blocks -->
                                </DataTemplate>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                    <!-- More triggers -->
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</HierarchicalDataTemplate>

Yes, it's verbose. (You can define the templates for the different types as keyed resources and then reference them in the Setters though)

Upvotes: 9

yo chauhan
yo chauhan

Reputation: 12295

<Window.Resources>
    <local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>
</Window.Resources>
<Grid>
    <ListBox Width="400" Margin="10"
     ItemsSource="{Binding Source={StaticResource myTodoList}}"
     ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
     HorizontalContentAlignment="Stretch"/>
</Grid>
public class TaskListDataTemplateSelector : DataTemplateSelector
{
    public override DataTemplate
        SelectTemplate(object item, DependencyObject container)
    {
        FrameworkElement element = container as FrameworkElement;

        if (element != null && item != null && item is Task)
        {
            Task taskitem = item as Task;

            if (taskitem.Priority == 1)
                return
                    element.FindResource("importantTaskTemplate") as DataTemplate;
            else
                return
                    element.FindResource("myTaskTemplate") as DataTemplate;
        }

        return null;
    }
}

This is implemented for ListBox but the idea can be same for DataGrid/TreeView .I hope this will help.

Upvotes: 6

blindmeis
blindmeis

Reputation: 22445

one way is to use a TemplateSelector and within the selector do what you want depending on your BlockType.

or you create wrapperviewmodels like:

 public class ResultBlockBlock{}
 public class ResultBlockFile{}
 public class ResultBlockFolder{}

then you can go the DataTemplate DataType way

Upvotes: 1

Related Questions