Holly
Holly

Reputation: 81

TreeView with more than one column

I have a basic class that looks something like this:

public class Item
{
    private string      name;
    private bool        visible;
    private double      value;
    private Item        parent;
    private List<Item>  children = new List<Item>();
    …
}

I have a list of Items that I need to display in a treeview. For each Item I need to display the following fields:

I want to do so by using MVVM, so I've defined the following classes 'ItemViewModel' and 'ItemCollectionViewModel' to which I will bind my treeview.

I tried the following XAML:

<TreeView ItemsSource="{Binding ItemViewModelList}">
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
            <Setter Property="FontWeight" Value="Normal" />
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="FontWeight" Value="Bold" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </TreeView.ItemContainerStyle>

    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition SharedSizeGroup="VisibiltyCol" />
                    <ColumnDefinition SharedSizeGroup="NameCol" />
                    <ColumnDefinition SharedSizeGroup="ValueCol" />
                </Grid.ColumnDefinitions>
                <CheckBox  Grid.Column="0" IsChecked="{Binding Visible}"  Margin="5" />
                <TextBlock Grid.Column="1" Text="{Binding Name}" Margin="5" />
                <Slider    Grid.Column="2" Value="{Binding Value}" Width="100" Margin="10, 0, 0, 0" Maximum="1" />
            </Grid>

        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>

</TreeView>

It works fine, except that I want all the sliders to be right below each other, and they are not. (Just those who are at the same level of hierarchy appear right under each other).

In other words, I need the tree to display the sliders (representing the 'Value' property) in another column.

Can someone help?

Upvotes: 3

Views: 6207

Answers (1)

Lee Louviere
Lee Louviere

Reputation: 5262

  • Make the grids stretch (so horizontalalignment.stretch), make the items in the treeview stretch as well (horizontalcontentalignment.stretch), whatever it takes to do that. Then have the third column have a shared column size.
  • You'll need this custom TreeViewItem style. Also attached below.

Then the TreeView would look like this.

    <TreeView HorizontalContentAlignment="Stretch" Name="DTV" ItemsSource="{Binding DTVIList}" Grid.Row="1"
              ItemContainerStyle="{StaticResource TreeViewItemStyle1}">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                <Grid HorizontalAlignment="Stretch">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="1*"/>
                        <ColumnDefinition Width="100" SharedSizeGroup="SliderColumn"/>
                    </Grid.ColumnDefinitions>
                    <CheckBox  Grid.Column="0" IsChecked="{Binding Visible}"  Margin="5" />
                    <TextBlock Grid.Column="1" Text="{Binding Name}" Margin="5" />
                    <Slider    Grid.Column="2" Value="{Binding Value}" Width="100" Margin="10, 0, 0, 0" Maximum="1" />                            
                </Grid>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>

This should do it.

TreeViewStyle attached:

<Style x:Key="TreeViewItemFocusVisual">
  <Setter Property="Control.Template">
    <Setter.Value>
      <ControlTemplate>
        <Rectangle/>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<PathGeometry x:Key="TreeArrow" Figures="M0,0 L0,6 L6,0 z"/>

<Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
  <Setter Property="Focusable" Value="False"/>
  <Setter Property="Width" Value="16"/>
  <Setter Property="Height" Value="16"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type ToggleButton}">
        <Border Width="16" Height="16" Background="Transparent" Padding="5,5,5,5">
          <Path x:Name="ExpandPath" Fill="Transparent" Stroke="#FF989898" Data="{StaticResource TreeArrow}">
            <Path.RenderTransform>
              <RotateTransform Angle="135" CenterX="3" CenterY="3"/>
            </Path.RenderTransform>
          </Path>
        </Border>
        <ControlTemplate.Triggers>
          <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF1BBBFA"/>
            <Setter Property="Fill" TargetName="ExpandPath" Value="Transparent"/>
          </Trigger>
          <Trigger Property="IsChecked" Value="True">
            <Setter Property="RenderTransform" TargetName="ExpandPath">
              <Setter.Value>
                <RotateTransform Angle="180" CenterX="3" CenterY="3"/>
              </Setter.Value>
            </Setter>
            <Setter Property="Fill" TargetName="ExpandPath" Value="#FF595959"/>
            <Setter Property="Stroke" TargetName="ExpandPath" Value="#FF262626"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
<Style x:Key="TreeViewItemStyle1" TargetType="{x:Type TreeViewItem}">
  <Setter Property="Background" Value="Transparent"/>
  <Setter Property="HorizontalContentAlignment" Value="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
  <Setter Property="VerticalContentAlignment" Value="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
  <Setter Property="Padding" Value="1,0,0,0"/>
  <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
  <Setter Property="FocusVisualStyle" Value="{StaticResource TreeViewItemFocusVisual}"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type 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 x:Name="Expander" Style="{StaticResource ExpandCollapseToggleStyle}" ClickMode="Press" IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"/>
          <Border x:Name="Bd" SnapsToDevicePixels="true" Grid.Column="1" Grid.ColumnSpan="2" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
            <ContentPresenter x:Name="PART_Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" ContentSource="Header"/>
          </Border>
          <ItemsPresenter x:Name="ItemsHost" Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="1"/>
        </Grid>
        <ControlTemplate.Triggers>
          <Trigger Property="IsExpanded" Value="false">
            <Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
          </Trigger>
          <Trigger Property="HasItems" Value="false">
            <Setter Property="Visibility" TargetName="Expander" Value="Hidden"/>
          </Trigger>
          <Trigger Property="IsSelected" Value="true">
            <Setter Property="Background" TargetName="Bd" 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 Property="Background" TargetName="Bd" 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>

Upvotes: 7

Related Questions