0

I have an application on production with a TreeView control but when the client want to expand or collapse the tree, he finds it very annoying to click on the toggle button because the button is too small. I have tried everything to restyle the button, but either it messes with my other control or I lose completely the functionality of Expand/Collapse when I succeed on styling it. Here is the button : enter image description here

Here is how my code works :

<ListBox.ItemTemplate>
    <DataTemplate>
        <TreeView x:Name="EntityTreeView" BorderThickness="0">
            <HeaderedContentControl>
                <StackPanel Orientation="Horizontal" Margin="0,0,0,0" >
                    
                    .....

                </StackPanel>
            </HeaderedContentControl>
            <TreeViewItem>
                <ScrollViewer HorizontalScrollBarVisibility="Auto" MaxHeight="300">
                    <StackPanel Orientation="Horizontal">
                        <Grid Name="Cursor" Height="50" Width="50" Focusable="False">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition/>
                                <RowDefinition/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
                           ....
                        </Grid>
                        <!-- Entity's parameter list -->
                        <ListBox Grid.Column="1" x:Name="parametersList" ItemsSource="{Binding Path=Parameters, UpdateSourceTrigger=PropertyChanged}" BorderThickness="0">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel Orientation="Horizontal" Visibility="{Binding Path=Visible}">
                                        .....
                                    </StackPanel>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                    </StackPanel>
                </ScrollViewer>
            </TreeViewItem>
        </TreeView>
    </DataTemplate>
</ListBox.ItemTemplate>

This is what I'm trying to make it work :

</ResourceDictionary>
    <!-- Style for TreeView expanders that are too small -->
    <!-- Toggle Button -->
    <Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
        <Setter Property="Focusable" Value="False"/>
        <Setter Property="Width" Value="24"/>
        <Setter Property="Height" Value="24"/>
        <Setter Property="Padding" Value="4"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ToggleButton">
                    <Grid Width="24" Height="24">
                        <ContentPresenter/>
                        <Path x:Name="Arrow" Fill="Black" Data="M 5,10 L 15,10 L 10,15 Z"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="True">
                            <Setter TargetName="Arrow" Property="Data" Value="M 5,5 L 15,10 L 5,15 Z"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <!-- TreeViewItem Style (Automatically Applies Expander Style) -->
    <Style TargetType="TreeViewItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TreeViewItem">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>

                        <!-- Custom Expander Button -->
                        <ToggleButton x:Name="Expander"
                              IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" 
                              Style="{StaticResource ExpandCollapseToggleStyle}"/>

                        <!-- TreeViewItem Header -->
                        <ContentPresenter Grid.Column="1" ContentSource="Header" Margin="5,0,0,0"/>

                        <!-- Items Presenter -->
                        <ItemsPresenter Grid.Column="1" Margin="20,0,0,0"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
3
  • apply LayoutTransfor ScaleTransform on Grid Width="24" Height="24" Commented Apr 4 at 14:24
  • Such questions are farily easy to be answered with minimal reproducible example, but without they are just wasting of time, sorry. Please spend your time to save our. Commented Apr 4 at 16:37
  • The ToggleButton "Padding" (of 4) effectively reduces the Content "area" to 16x16 (from 24x24); whereas most (icon) buttons are 32x32 or slighty bigger (40; 44; 48). 16 is about the minimum for a scrollbar "thumb"; but it's not wedged in between other buttons (e.g. a toolbar; where "touching" multiple buttons will ofter occur with anything less than 32x32). Commented Apr 5 at 0:45

1 Answer 1

0

I added a Border to your ToggleButton to make it easier to click.

ToggleButton:

            <Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
                <Setter Property="Focusable" Value="False"/>
                <Setter Property="Width" Value="24"/>
                <Setter Property="Height" Value="24"/>
                <Setter Property="Padding" Value="4"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ToggleButton">
                            <Grid Width="24" Height="24">
                                <Border Background="White" Opacity="0.001"/>
                                <ContentPresenter/>
                                <Path x:Name="Arrow" Fill="Black" Data="M 5,10 L 15,10 L 10,15 Z"/>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsChecked" Value="True">
                                    <Setter TargetName="Arrow" Property="Data" Value="M 5,5 L 15,10 L 5,15 Z"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

TreeViewItem:

            <Style TargetType="TreeViewItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="TreeViewItem">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition MinWidth="19" Width="Auto"/>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>

                                <ToggleButton Margin="-1,0,0,0" x:Name="Expander" Style="{StaticResource ExpandCollapseToggleStyle}" IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" ClickMode="Press"/>
                                <Border Name="Bd" Grid.Column="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
                                    <ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" MinWidth="20"/>
                                </Border>
                                <ItemsPresenter x:Name="ItemsHost" Grid.Row="1" 
                    Grid.Column="1" Grid.ColumnSpan="2"/>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsExpanded" Value="false">
                                    <Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed"/>
                                </Trigger>
                                <Trigger Property="HasItems" Value="false">
                                    <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/>
                                </Trigger>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="HasHeader" Value="false"/>
                                        <Condition Property="Width" Value="Auto"/>
                                    </MultiTrigger.Conditions>
                                    <Setter TargetName="PART_Header" Property="MinWidth" Value="75"/>
                                </MultiTrigger>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="HasHeader" Value="false"/>
                                        <Condition Property="Height" Value="Auto"/>
                                    </MultiTrigger.Conditions>
                                    <Setter TargetName="PART_Header" Property="MinHeight" Value="19"/>
                                </MultiTrigger>
                                <Trigger Property="IsSelected" Value="true">
                                    <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                                </Trigger>
                                <MultiTrigger>
                                    <MultiTrigger.Conditions>
                                        <Condition Property="IsSelected" Value="true"/>
                                        <Condition Property="IsSelectionActive" Value="false"/>
                                    </MultiTrigger.Conditions>
                                    <Setter TargetName="Bd" Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                                </MultiTrigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

enter image description here

Sign up to request clarification or add additional context in comments.

3 Comments

You're a life savior, thank you so much. That's what I needed !
You're welcome, I love working with WPF.
Xaml is really not my cup of tea T.T

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.