0

I want to build a web page–like effect that displays a directory tree with multi-level nesting. The left side should show the directory names, and the right side should display operation buttons aligned to the right. I’ve tried many methods but couldn’t make it work—this is the current result.

nested item in listview with addition button
The directory nodes on the left are displayed correctly, but the operation buttons on the right are indented along with them. This is not the effect I want—I’d like the buttons on the right to be right-aligned instead.

my xaml code

<UserControl x:Class="GeoRoad.UI.Dir.SectionDirControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:GeoRoad.UI.Dir"
             mc:Ignorable="d" Height="302" Width="203">

    <UserControl.Resources>
        <local:DirTypeToIconConverter x:Key="DirTypeToIconConverter"/>

        <!-- 按钮无边框样式 -->
        <Style x:Key="IconButtonStyle" TargetType="Button">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="Padding" Value="0"/>
            <Setter Property="Margin" Value="2,0,0,0"/>
            <Setter Property="Cursor" Value="Hand"/>
        </Style>
    </UserControl.Resources>

    <Grid>
        <TreeView ItemsSource="{Binding Nodes}">
            <TreeView.ItemContainerStyle>
                <Style TargetType="TreeViewItem">
                    <!-- 让 TreeViewItem 的内容宽度撑满整行 -->
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                </Style>
            </TreeView.ItemContainerStyle>
            
            <TreeView.ItemTemplate>
                                
                <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                    <DockPanel LastChildFill="True" >
                        <StackPanel Orientation="Horizontal" DockPanel.Dock="Right" >
                            <Button Style="{StaticResource IconButtonStyle}"
                                    Command="{Binding DataContext.NewDirCommand, RelativeSource={RelativeSource AncestorType=TreeView}}"
                                    CommandParameter="{Binding}">
                                <Image Source="pack://application:,,,/GeoRoad.UI.Net8;component/Resources/icons8-add-48.png" Width="16" Height="16"/>
                            </Button>

                            <Button Style="{StaticResource IconButtonStyle}"
                                    Command="{Binding DataContext.RenameCommand, RelativeSource={RelativeSource AncestorType=TreeView}}"
                                    CommandParameter="{Binding}">
                                <Image Source="pack://application:,,,/GeoRoad.UI.Net8;component/Resources/icons8-rename-48.png" Width="16" Height="16"/>
                            </Button>

                            <Button Style="{StaticResource IconButtonStyle}"
                                    Command="{Binding DataContext.DeleteDirCommand, RelativeSource={RelativeSource AncestorType=TreeView}}"
                                    CommandParameter="{Binding}">
                                <Image Source="pack://application:,,,/GeoRoad.UI.Net8;component/Resources/icons8-delete-48.png" Width="16" Height="16"/>
                            </Button>
                        </StackPanel>

                        <StackPanel Orientation="Horizontal" >
                            <Image Width="16" Height="16" Margin="0,0,5,0"
                                    Source="{Binding Type, Converter={StaticResource DirTypeToIconConverter}}"/>
                            <TextBlock Text="{Binding Name}" VerticalAlignment="Center"/>
                        </StackPanel>
                    </DockPanel>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>
</UserControl>

is any idea? tks.

1
  • make sure that treeView control has enough width, or treeViewItem, you can start experimenting with applying width directly to some controls (treeView, treeViewItem and inner template), after some time you will find out where the problem is. Commented Oct 2 at 9:46

1 Answer 1

0

IIRC, you can achieve this by creating custom TreeView and TreeViewItem:

public class TreeViewItemEx : TreeViewItem
{
    public TreeViewItemEx()
    {
        this.Loaded += TreeViewItemEx_Loaded;
    }

    protected override DependencyObject GetContainerForItemOverride() => new TreeViewItemEx();

    protected override bool IsItemItsOwnContainerOverride(object item) => item is TreeViewItemEx;

    private void TreeViewItemEx_Loaded(object sender, RoutedEventArgs e)
    {
        if (VisualChildrenCount <= 0 ||
            GetVisualChild(0) is not Grid grid ||
            grid.ColumnDefinitions.Count != 3)
        {
            return;
        }

        // Remove the third column 
        // and make the second column take all available space.
        grid.ColumnDefinitions.RemoveAt(2);
        grid.ColumnDefinitions[1].Width = new GridLength(1, GridUnitType.Star);
    }
}
public class TreeViewEx : TreeView
{
    protected override DependencyObject GetContainerForItemOverride() => new TreeViewItemEx();

    protected override bool IsItemItsOwnContainerOverride(object item) => item is TreeViewItemEx;
}

and use them like this:

<local:TreeViewEx ItemsSource="{Binding Items}">
    <local:TreeViewEx.ItemContainerStyle>
        <Style TargetType="local:TreeViewItemEx">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        </Style>
    </local:TreeViewEx.ItemContainerStyle>
    <local:TreeViewEx.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0" Text="{Binding Name}" />
                <StackPanel
                    Grid.Column="1"
                    HorizontalAlignment="Right"
                    Orientation="Horizontal">
                    <Button Content="A" />
                    <Button Content="B" />
                    <Button Content="C" />
                </StackPanel>
            </Grid>
        </HierarchicalDataTemplate>
    </local:TreeViewEx.ItemTemplate>
</local:TreeViewEx>
Sign up to request clarification or add additional context in comments.

1 Comment

tks, it can work.

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.