1

So I have a TreeViewItem that has the following style:

                   <Style TargetType="{x:Type TreeViewItem}">
                        <Setter Property="HeaderTemplate">
                            <Setter.Value>
                                <DataTemplate>
                                    <StackPanel Orientation="Horizontal">
                                        <Image Name="img" Width="20" Height="16" Stretch="Uniform" Source="Images/Folder.png"/>
                                        <TextBlock Text="{Binding}" Margin="5,0" />
                                    </StackPanel>
                                </DataTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>

When selected, the TextBlock AND Image are highlighted. I'm trying to just highlight the TextBlock so it functions like the folders tree in file explorer.

AKoran
  • 1,846
  • 6
  • 22
  • 36

2 Answers2

1

I've found a (somewhat hacky) but lightweight solution to this problem. I see that this question is pretty old, but nonetheless, I'll post the solution here for others to find.

In my TreeView, I override the two brushes used for setting the background of the TreeViewItem when its selection changes. I also create copies of the brushes so I can restore them later in my data template:

<TreeView ItemsSource="{Binding Path=SomeDataSource}">
    <TreeView.Resources>
         <SolidColorBrush x:Key="_CustomHighlightBrushKey" Color="{Binding Source={StaticResource {x:Static SystemColors.HighlightBrushKey}}, Path=Color}" />
         <SolidColorBrush x:Key="_CustomControlBrushKey" Color="{Binding Source={StaticResource {x:Static SystemColors.ControlBrushKey}}, Path=Color}" />
         <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
         <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
    </TreeView.Resources>
</TreeView>

Note that I couldn't get this to work with a DynamicResource binding, so this solution probably won't work with theme changes. I would be very interested to know if there is a way to do this.

I then use the following hierarchical data template for formatting tree nodes:

<HierarchicalDataTemplate DataType="{x:Type SomeViewModelType}" ItemsSource="{Binding Path=Children}">
    <StackPanel Orientation="Horizontal">
        <StackPanel.Resources>
            <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="{Binding Source={StaticResource {x:Static SystemColors.HighlightBrushKey}}, Path=Color}" />
            <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="{Binding Source={StaticResource {x:Static SystemColors.ControlBrushKey}}, Path=Color}" />
        </StackPanel.Resources>
        <Image SnapsToDevicePixels="True" Source="...">
        </Image>
        <TextBlock Text="{Binding Path=DisplayName}" Margin="5,0">
            <TextBlock.Resources>
                <Style TargetType="{x:Type TextBlock}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=IsSelected}" Value="True">
                            <Setter Property="Background" Value="{DynamicResource _CustomHighlightBrushKey}" />
                        </DataTrigger>
                        <MultiDataTrigger>
                            <MultiDataTrigger.Conditions>
                                <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=IsSelected}" Value="True" />
                                <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=IsSelectionActive}" Value="False" />
                            </MultiDataTrigger.Conditions>
                            <Setter Property="Background" Value="{DynamicResource _CustomControlBrushKey}" />
                        </MultiDataTrigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Resources>
        </TextBlock>
    </StackPanel>
</HierarchicalDataTemplate>

Note that I restore the system brushes to their original (static) values so context menus can be rendered correctly.

Ulrik Rasmussen
  • 1,098
  • 1
  • 8
  • 25
0

You will need to roll your own highlight mark up, so instead of letting the control painting the entire panel background blue, you set your own highlight formatting based on a trigger when TreeViewItem.IsSelected is True.

In your case this would be setting the text container background to blue (when set, white normally) and leaving the image container background as white, whilst setting the overall container background to white.

The method is described here: link text

Guy
  • 3,353
  • 24
  • 28
  • 1
    That makes sense, but it's not quite as easy as in the example you provided. Each time I try to use TargetName to address the TextBlock I get an error saying it cannot be accessed. – AKoran Nov 10 '09 at 14:40
  • http://stackoverflow.com/questions/248545/wpf-trigger-for-isselected-in-a-datatemplate-for-listbox-items – Guy Nov 10 '09 at 15:52
  • Don't take this the wrong way, but it doesn't help a newbie to WPF much when you point to an example that just kinda is close to what I'm trying to do. No matter what I try, every time I refer back to the TextBlock I get a "TargetName property cannot be set on a Style Setter" error. – AKoran Nov 10 '09 at 18:44
  • I think the reason you are getting that error is because a style setter will always set the property on the control which uses that style, which can be redirected by a TargetName property. If you look in the first example I posted, the trigger is not part of a style, its just part of the control template, and I think that may be where you are going wrong. – Guy Nov 11 '09 at 13:30