0

I tried to set up a custom styled treeview that does "just in time" loading by two-way binding the expanded property to a similar property in the view-model. The style and functionality aspects work fine on their own, but not when put together.

When I do it like this the functionality is there:

<TreeView Name="treeView" ItemsSource="{Binding}" Grid.Column="0">
    <TreeView.Resources>
        <ResourceDictionary  Source="GroupedTreeViewItemStyle.xaml"/>
    </TreeView.Resources>

    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Setter Property="IsExpanded"  Value="{Binding Expanded, Mode=TwoWay}"/>
        </Style>
    </TreeView.ItemContainerStyle>
</TreeView>

But when I add the BasedOn to use my custom style it does no longer load any nodes. I use my style by replacing the above style definition with the following:

<Style TargetType="TreeViewItem" BasedOn="{StaticResource GroupedTreeViewItemStyle}">

And here is my custom style based on this tutorial:

<ResourceDictionary  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:this="*******namespace omitted*******">

<!-- This Style redefines the ControlTemplate used by TreeViewItems and
   also provides a different itemspanel for their child items. -->
<Style TargetType="TreeViewItem" x:Key="GroupedTreeViewItemStyle">
    <Style.Resources>
        <LinearGradientBrush x:Key="ItemAreaBrush" StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1">
            <GradientStop Color="#fff" Offset="0" />
            <GradientStop Color="#f2fcfe" Offset="1" />
        </LinearGradientBrush>
        <LinearGradientBrush x:Key="SelectedItemAreaBrush" StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1">
            <GradientStop Color="#fff" Offset="0" />
            <GradientStop Color="#f2fcfe" Offset="1" />
        </LinearGradientBrush>
        <LinearGradientBrush x:Key="ItemBorderBrush" StartPoint="0.5, 0" EndPoint="0.5, 1">
            <GradientStop Color="#243B55" Offset="0" />
            <GradientStop Color="#141E30" Offset="1" />
        </LinearGradientBrush>
        <LinearGradientBrush x:Key="SelectedItemBorderBrush" StartPoint="0.5, 0" EndPoint="0.5, 1">
            <GradientStop Color="#243B55" Offset="0" />
            <GradientStop Color="#141E30" Offset="1" />
        </LinearGradientBrush>

        <DropShadowBitmapEffect x:Key="DropShadowEffect" />
    </Style.Resources>



    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TreeViewItem">
                <Grid Margin="8,4">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>

                    <!-- This Border contains elements which display 
             the content and child items of the TreeViewItem. -->
                    <Border Name="Bd" 
          Background="{StaticResource ItemAreaBrush}"
          BorderBrush="{StaticResource ItemBorderBrush}" 
          BorderThickness="0.6" 
          CornerRadius="8"              
          Padding="6"     
          SnapsToDevicePixels="True"
          >
                        <Grid>
                            <!-- Items with children are 
                 shown in an Expander. -->
                            <Expander Name="Exp" IsExpanded="{TemplateBinding TreeViewItem.IsExpanded}">
                                <Expander.Header>
                                    <!-- Displays the item's header in the Expander. -->
                                    <ContentPresenter ContentSource="Header" />
                                </Expander.Header>
                                <!-- Displays the item's children. -->
                                <ItemsPresenter />
                            </Expander>

                            <!-- Items without children are 
                 shown in a ContentPresenter. -->
                            <ContentPresenter Name="CntPres"
              ContentSource="Header"
              HorizontalAlignment="Center"
              VerticalAlignment="Center"
              Visibility="Collapsed" 
              />
                        </Grid>
                    </Border>
                </Grid>

                <ControlTemplate.Triggers>
                    <!-- If the TreeViewItem has child items,
             show it in an Expander.  Otherwise
             hide the Expander and show the hidden
             ContentPresenter. -->
                    <Trigger Property="TreeViewItem.HasItems" Value="false">
                        <Setter 
            TargetName="Exp" 
            Property="Visibility" 
            Value="Collapsed" />
                        <Setter 
            TargetName="CntPres" 
            Property="Visibility" 
            Value="Visible" />
                    </Trigger>

                    <!--When the item is selected in the TreeView, use the 
            "selected" colors and give it a drop shadow. -->
                    <Trigger Property="IsSelected" Value="true">
                        <Setter
            TargetName="Bd"
            Property="Panel.Background"                     
            Value="{StaticResource SelectedItemAreaBrush}" />
                        <Setter
            TargetName="Bd"
            Property="Border.BorderBrush"                     
            Value="{StaticResource SelectedItemBorderBrush}" />
                        <!--<Setter
            TargetName="Bd"
            Property="TextElement.Foreground"                   
            Value="{DynamicResource 
              {x:Static SystemColors.HighlightTextBrushKey}}" />-->
                        <Setter
            TargetName="Bd"
            Property="Border.BitmapEffect"                  
            Value="{StaticResource DropShadowEffect}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

    <!-- Make each TreeViewItem show it's children 
     in a StackPanel. If it is a root item then
     the Orientation will be 'Horizontal', else
     'Vertical'. -->
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <ItemsPanelTemplate.Resources>
                    <this:ItemsPanelOrientationConverter x:Key="conv" />
                </ItemsPanelTemplate.Resources>
                <StackPanel 
        IsItemsHost="True" 
        Orientation="{Binding 
          RelativeSource={x:Static RelativeSource.TemplatedParent}, 
          Converter={StaticResource conv}}" 
        />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>


</Style>

Does anybody know, what I am doing wrong in combining the style and functionality of my tree? Is the problem that the style already defines something according to the isExpanded property? Or is there something missing, something along the lines of super(isExpanded)?

Thanks for your help!

Ruben Bohnet
  • 392
  • 1
  • 12

1 Answers1

1

Expander binding is probably the cause of the issue:

<Expander Name="Exp" IsExpanded="{TemplateBinding TreeViewItem.IsExpanded}">

according to documentation,

A TemplateBinding is always a one-way binding, even if properties involved default to two-way binding.

(see also TemplateBinding limitations)

try re-write binding as:

<Expander Name="Exp" 
          IsExpanded="{Binding IsExpanded, 
                               RelativeSource={RelativeSource TemplatedParent}}">
ASh
  • 34,632
  • 9
  • 60
  • 82