Reputation: 17831
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
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
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
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