Mg Bhadurudeen
Mg Bhadurudeen

Reputation: 1434

How to set background color of TreeView node?

We add root nodes to TreeView control as below. But how to set background color of that root node. Also set bg-color to any currently selected Item? (I guess, every node is a TreeViewItem, But I am unable to retrieve it from nodes)

TreeViewNode rootNode1 = new TreeViewNode() {Content = "Flavors"};
sampleTreeView.RootNodes.Add(rootNode1);

Upvotes: 1

Views: 1762

Answers (2)

mm8
mm8

Reputation: 169190

The easiest way to change the background colour of all items would be to override the TreeViewItemBackground ThemeResource like this:

<TreeView>
    <TreeView.Resources>
        <ResourceDictionary>
            <ResourceDictionary.ThemeDictionaries>
                <ResourceDictionary x:Key="Default">
                    <SolidColorBrush x:Key="TreeViewItemBackground">Red</SolidColorBrush>
                </ResourceDictionary>
            </ResourceDictionary.ThemeDictionaries>
        </ResourceDictionary>
    </TreeView.Resources>
</TreeView>

If you want to change the colour of the selected ones you do the same for the TreeViewItemBackgroundSelected resource.

Changing the background colour of the root nodes only requires a bit more effort. You will have to extract the default styles and templates. Once you have done this you could handle the Loaded event of the root Grid element in the TreeViewItem's ControlTemplate and programmatically check whether the TreeViewItem's content has any child nodes. Please refer to the following sample markup.

<TreeView x:Name="treeView">
    <TreeView.RootNodes>
        <TreeViewNode Content="Root A">
            <TreeViewNode.Children>
                <TreeViewNode Content="a" />
                <TreeViewNode Content="b" />
                <TreeViewNode Content="c" />
            </TreeViewNode.Children>
        </TreeViewNode>
        <TreeViewNode Content="Root B">
            <TreeViewNode.Children>
                <TreeViewNode Content="d" />
                <TreeViewNode Content="e" />
                <TreeViewNode Content="f" />
            </TreeViewNode.Children>
        </TreeViewNode>
    </TreeView.RootNodes>
    <TreeView.Resources>
        <Style x:Key="BaseTextBlockStyle" TargetType="TextBlock">
            <Setter Property="FontFamily" Value="XamlAutoFontFamily"/>
            <Setter Property="FontWeight" Value="SemiBold"/>
            <Setter Property="FontSize" Value="15"/>
            <Setter Property="TextTrimming" Value="None"/>
            <Setter Property="TextWrapping" Value="Wrap"/>
            <Setter Property="LineStackingStrategy" Value="MaxHeight"/>
            <Setter Property="TextLineBounds" Value="Full"/>
        </Style>
        <Style x:Key="BodyTextBlockStyle" BasedOn="{StaticResource BaseTextBlockStyle}" TargetType="TextBlock">
            <Setter Property="FontWeight" Value="Normal"/>
            <Setter Property="FontSize" Value="15"/>
        </Style>
        <Style x:Key="CaptionTextBlockStyle" BasedOn="{StaticResource BaseTextBlockStyle}" TargetType="TextBlock">
            <Setter Property="FontSize" Value="12"/>
            <Setter Property="FontWeight" Value="Normal"/>
        </Style>
        <DataTemplate x:Key="TreeViewItemDataTemplate">
            <Grid Height="44">
                <TextBlock HorizontalAlignment="Left" Style="{ThemeResource BodyTextBlockStyle}" Text="{Binding Content}" VerticalAlignment="Center"/>
            </Grid>
        </DataTemplate>
    </TreeView.Resources>
    <TreeView.Template>
        <ControlTemplate TargetType="TreeView">
            <TreeViewList x:Name="ListControl" AllowDrop="True" CanReorderItems="True" CanDragItems="True" 
                                  ItemTemplate="{StaticResource TreeViewItemDataTemplate}">
                <TreeViewList.ItemContainerStyle>
                    <Style TargetType="TreeViewItem">
                        <Setter Property="Padding" Value="0"/>
                        <Setter Property="Background" Value="{ThemeResource TreeViewItemBackground}"/>
                        <Setter Property="BorderBrush" Value="{ThemeResource TreeViewItemBorderBrush}"/>
                        <Setter Property="BorderThickness" Value="{ThemeResource TreeViewItemBorderThemeThickness}"/>
                        <Setter Property="GlyphBrush" Value="{ThemeResource TreeViewItemForeground}"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="TreeViewItem">
                                    <Grid x:Name="ContentPresenterGrid" 
                                                  Background="{TemplateBinding Background}" 
                                                  BorderThickness="{TemplateBinding BorderThickness}" 
                                                  BorderBrush="{TemplateBinding BorderBrush}" 
                                                  Margin="0,0,0,0"
                                                  Loaded="ContentPresenterGrid_Loaded">
                                        <VisualStateManager.VisualStateGroups>
                                            ...
                                        </VisualStateManager.VisualStateGroups>
                                        <Grid x:Name="MultiSelectGrid">
                                            <Grid.Resources>
                                                <Style x:Name="TreeViewMultiSelectCheckBox" TargetType="CheckBox">
                                                    <Setter Property="Background" Value="{ThemeResource CheckBoxBackgroundUnchecked}"/>
                                                    <Setter Property="Foreground" Value="{ThemeResource CheckBoxForegroundUnchecked}"/>
                                                    <Setter Property="BorderBrush" Value="{ThemeResource CheckBoxBorderBrushUnchecked}"/>
                                                    <Setter Property="HorizontalAlignment" Value="Left"/>
                                                    <Setter Property="VerticalAlignment" Value="Center"/>
                                                    <Setter Property="HorizontalContentAlignment" Value="Left"/>
                                                    <Setter Property="VerticalContentAlignment" Value="Top"/>
                                                    <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
                                                    <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
                                                    <Setter Property="MinWidth" Value="32"/>
                                                    <Setter Property="MinHeight" Value="32"/>
                                                    <Setter Property="Template">
                                                        <Setter.Value>
                                                            <ControlTemplate TargetType="CheckBox">
                                                                <Grid x:Name="RootGrid" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Width="32">
                                                                    <VisualStateManager.VisualStateGroups>
                                                                        <VisualStateGroup x:Name="CombinedStates">
                                                                            <VisualState x:Name="UncheckedNormal">
                                                                                <Storyboard>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Foreground">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource CheckBoxCheckGlyphForegroundUnchecked}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                </Storyboard>
                                                                            </VisualState>
                                                                            <VisualState x:Name="UncheckedPointerOver">
                                                                                <Storyboard>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Foreground">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource CheckBoxCheckGlyphForegroundUncheckedPointerOver}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                </Storyboard>
                                                                            </VisualState>
                                                                            <VisualState x:Name="UncheckedPressed">
                                                                                <Storyboard>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Foreground">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource CheckBoxCheckGlyphForegroundUncheckedPressed}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                </Storyboard>
                                                                            </VisualState>
                                                                            <VisualState x:Name="UncheckedDisabled">
                                                                                <Storyboard>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Foreground">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource CheckBoxCheckGlyphForegroundUncheckedDisabled}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                </Storyboard>
                                                                            </VisualState>
                                                                            <VisualState x:Name="CheckedNormal">
                                                                                <Storyboard>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalRectangle" Storyboard.TargetProperty="Fill">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TreeViewItemCheckBoxBackgroundSelected}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalRectangle" Storyboard.TargetProperty="Stroke">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TreeViewItemCheckBoxBorderSelected}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Foreground">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TreeViewItemCheckGlyphSelected}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                    <DoubleAnimation Duration="0" Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Opacity" To="1"/>
                                                                                </Storyboard>
                                                                            </VisualState>
                                                                            <VisualState x:Name="CheckedPointerOver">
                                                                                <Storyboard>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalRectangle" Storyboard.TargetProperty="Fill">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TreeViewItemCheckBoxBackgroundSelected}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalRectangle" Storyboard.TargetProperty="Stroke">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TreeViewItemCheckBoxBorderSelected}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Foreground">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TreeViewItemCheckGlyphSelected}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                    <DoubleAnimation Duration="0" Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Opacity" To="1"/>
                                                                                </Storyboard>
                                                                            </VisualState>
                                                                            <VisualState x:Name="CheckedPressed">
                                                                                <Storyboard>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalRectangle" Storyboard.TargetProperty="Fill">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TreeViewItemCheckBoxBackgroundSelected}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalRectangle" Storyboard.TargetProperty="Stroke">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TreeViewItemCheckBoxBorderSelected}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Foreground">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TreeViewItemCheckGlyphSelected}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                    <DoubleAnimation Duration="0" Storyboard.TargetName="NormalRectangle" Storyboard.TargetProperty="StrokeThickness" To="{ThemeResource CheckBoxCheckedStrokeThickness}"/>
                                                                                    <DoubleAnimation Duration="0" Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Opacity" To="1"/>
                                                                                </Storyboard>
                                                                            </VisualState>
                                                                            <VisualState x:Name="CheckedDisabled">
                                                                                <Storyboard>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalRectangle" Storyboard.TargetProperty="Fill">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TreeViewItemCheckBoxBackgroundSelected}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalRectangle" Storyboard.TargetProperty="Stroke">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TreeViewItemCheckBoxBorderSelected}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Foreground">
                                                                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TreeViewItemCheckGlyphSelected}"/>
                                                                                    </ObjectAnimationUsingKeyFrames>
                                                                                    <DoubleAnimation Duration="0" Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Opacity" To="1"/>
                                                                                </Storyboard>
                                                                            </VisualState>
                                                                        </VisualStateGroup>
                                                                    </VisualStateManager.VisualStateGroups>
                                                                    <Grid Height="32" VerticalAlignment="Stretch">
                                                                        <Rectangle x:Name="NormalRectangle" Fill="{ThemeResource CheckBoxCheckBackgroundFillUnchecked}" HorizontalAlignment="Center" Height="20" StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}" Stroke="{ThemeResource CheckBoxCheckBackgroundStrokeUnchecked}" UseLayoutRounding="False" VerticalAlignment="Center" Width="20"/>
                                                                        <FontIcon x:Name="CheckGlyph" FontFamily="{ThemeResource SymbolThemeFontFamily}" Foreground="{ThemeResource CheckBoxCheckGlyphForegroundUnchecked}" FontSize="20" Glyph="&#xE001;" Opacity="0"/>
                                                                    </Grid>
                                                                </Grid>
                                                            </ControlTemplate>
                                                        </Setter.Value>
                                                    </Setter>
                                                </Style>
                                            </Grid.Resources>
                                            <StackPanel HorizontalAlignment="Stretch" Margin="{Binding TreeViewItemTemplateSettings.Indentation, RelativeSource={RelativeSource Mode=TemplatedParent}}" Orientation="Horizontal" VerticalAlignment="Stretch">
                                                <Grid>
                                                    <CheckBox x:Name="MultiSelectCheckBox" IsTabStop="False" Style="{StaticResource TreeViewMultiSelectCheckBox}" VerticalAlignment="Stretch" Visibility="Collapsed" Width="32"/>
                                                    <Border x:Name="MultiArrangeOverlayTextBorder" Background="{ThemeResource SystemControlBackgroundAccentBrush}" BorderThickness="2" BorderBrush="{ThemeResource SystemControlBackgroundChromeWhiteBrush}" HorizontalAlignment="Center" Height="20" IsHitTestVisible="False" MinWidth="20" Opacity="0" VerticalAlignment="Center">
                                                        <TextBlock x:Name="MultiArrangeOverlayText" AutomationProperties.AccessibilityView="Raw" HorizontalAlignment="Center" IsHitTestVisible="False" Style="{ThemeResource CaptionTextBlockStyle}" Text="{Binding TreeViewItemTemplateSettings.DragItemsCount, RelativeSource={RelativeSource Mode=TemplatedParent}}" VerticalAlignment="Center"/>
                                                    </Border>
                                                </Grid>
                                                <Grid x:Name="ExpandCollapseChevron" Background="Transparent" Opacity="{TemplateBinding GlyphOpacity}" Padding="12,0,12,0" Width="Auto">
                                                    <TextBlock FontFamily="{StaticResource SymbolThemeFontFamily}" Foreground="{TemplateBinding GlyphBrush}" FontSize="{TemplateBinding GlyphSize}" Height="12" Text="{TemplateBinding CollapsedGlyph}" VerticalAlignment="Center" Visibility="{Binding TreeViewItemTemplateSettings.CollapsedGlyphVisibility, RelativeSource={RelativeSource Mode=TemplatedParent}}" Width="12"/>
                                                    <TextBlock FontFamily="{StaticResource SymbolThemeFontFamily}" Foreground="{TemplateBinding GlyphBrush}" FontSize="{TemplateBinding GlyphSize}" Height="12" Text="{TemplateBinding ExpandedGlyph}" VerticalAlignment="Center" Visibility="{Binding TreeViewItemTemplateSettings.ExpandedGlyphVisibility, RelativeSource={RelativeSource Mode=TemplatedParent}}" Width="12"/>
                                                </Grid>
                                                <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentTransitions="{TemplateBinding ContentTransitions}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                            </StackPanel>
                                        </Grid>
                                    </Grid>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </TreeViewList.ItemContainerStyle>
                <TreeViewList.ItemContainerTransitions>
                    <TransitionCollection>
                        <ContentThemeTransition/>
                        <ReorderThemeTransition/>
                        <EntranceThemeTransition IsStaggeringEnabled="False"/>
                    </TransitionCollection>
                </TreeViewList.ItemContainerTransitions>
            </TreeViewList>
        </ControlTemplate>
    </TreeView.Template>
</TreeView>

...and the following code:

private void ContentPresenterGrid_Loaded(object sender, RoutedEventArgs e)
{
    Grid grid = (Grid)sender;
    TreeViewItem parent = FindParent<TreeViewItem>(grid);
    if (parent != null)
    {
        TreeViewNode node = parent.Content as TreeViewNode;
        if (node?.HasChildren == true)
            parent.Background = new SolidColorBrush(Windows.UI.Colors.Red);
    }
    grid.Loaded -= ContentPresenterGrid_Loaded;
}

private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
    DependencyObject parent = VisualTreeHelper.GetParent(dependencyObject);
    if (parent == null)
        return null;

    T parentT = parent as T;
    return parentT ?? FindParent<T>(parent);
}

It procudes the following result:

enter image description here

Upvotes: 1

Breeze Liu - MSFT
Breeze Liu - MSFT

Reputation: 3808

In the TreeView, every TreeViewNode is a TreeViewItem and they use the same TreeViewItemStyle. It doesn't expose a method to get TreeViewItem from the Node. But you can modify its style to make it looks different.

You can get the default style of TreeView by the following steps:

In the TreeView page, click the Document Outline tab, in the Document Outline window, you can find your TreeView, then you can create a default style for the treeView as the following image,

enter image description here

Then click OK to create a copy style, after that, you can see the style in your Page.Resources. You can change the style in the resouce to change Nodes' style and the select Node's background.

Here is the default style of the TreeView,

<Style x:Key="TreeViewStyle1" TargetType="TreeView">
    <Setter Property="IsTabStop" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TreeView">
                <TreeViewList x:Name="ListControl" AllowDrop="True"
                              CanReorderItems="True" CanDragItems="True"
                              ItemContainerStyle="{StaticResource TreeViewItemStyle}"
                              ItemTemplate="{StaticResource TreeViewItemDataTemplate}">
                    <TreeViewList.ItemContainerTransitions>
                        <TransitionCollection>
                            <ContentThemeTransition/>
                            <ReorderThemeTransition/>
                            <EntranceThemeTransition IsStaggeringEnabled="False"/>
                        </TransitionCollection>
                    </TreeViewList.ItemContainerTransitions>
                </TreeViewList>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

In this style, you can see the TreeViewList's ItemContainerStyle is using TreeViewItemStyle and its ItemTemplate is using TreeViewItemDataTemplate, you can also find them in this page's resource which is generated from our above steps.

To change Nodes' backgroud, you can modify the TreeViewItemDataTemplate as the following code by setting the Grid's Background to Red,

<DataTemplate x:Key="TreeViewItemDataTemplate">
    <Grid Height="44" Background="Red">
        <TextBlock HorizontalAlignment="Left"
                   Style="{ThemeResource BodyTextBlockStyle}" 
                   Text="{Binding Content}" VerticalAlignment="Center"/>
    </Grid>
</DataTemplate>

To set bg-color to any currently selected Item, you can modify the TreeViewItemStyle Selected VisualState,

...
    <VisualState x:Name="Selected">
        <VisualState.Setters>
            <Setter Target="ContentPresenterGrid.Background" Value="Green"/>
            <Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TreeViewItemForegroundSelected}"/>
            <Setter Target="ContentPresenterGrid.BorderBrush" Value="{ThemeResource TreeViewItemBorderBrushSelected}"/>
        </VisualState.Setters>
    </VisualState>
...

Moreover, you can also change the Node's background in a row by modifying the ContentPresenterGrid's background.

 <Grid x:Name="ContentPresenterGrid" Background="Yellow" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Margin="0,0,0,0">

Upvotes: 1

Related Questions