Я давно понял, что при попытке создать подобный интерфейс было то, что вы лучше , используя ListBox
, чем TreeView
.
Почему?
Если у вас есть только один уровень расширения (как видно из вашего примера), вы будете гораздо больше контролировать макет, поскольку у вас есть один DataTemplate
для стиля.
Настроить ListBox
намного проще, чем TreeView
, поскольку вам не нужно беспокоиться о GridViewColumnHeader
и GridViewColumnPresenters
и т. Д.
Чтобы получить часть расширения (именно поэтому вы изначально выбрали TreeView
), просто используйте Grid
с двумя определенными строками и Expander
во второй строке, связанной со свойством IsChecked
ToggleButton
. Смотрите пример, который я извлек из моего Log Viewer .
<DataTemplate>
<Grid Margin="0,0,0,3" Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30" SharedSizeGroup="SSG_TimeIcon"/>
<ColumnDefinition Width="120" SharedSizeGroup="SSG_Time"/>
<ColumnDefinition Width="30" SharedSizeGroup="SSG_LevelIcon"/>
<ColumnDefinition Width="70" SharedSizeGroup="SSG_Level"/>
<ColumnDefinition Width="*" SharedSizeGroup="SSG_Message"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- ProgramTime -->
<Rectangle Grid.Column="0" Grid.Row="0" Margin="0,0,0,0" Width="16" Height="16" VerticalAlignme="Top" HorizoalAlignme="Stretch" Fill="{StaticResource Icon_Timer}"/>
<TextBlock Grid.Column="1" Grid.Row="0" Margin="5,0,0,0" VerticalAlignme="Top" HorizoalAlignme="Stretch" Text="{Binding Path=TimeStamp, Converter={StaticResource ObjectToStringConverter}}" ToolTip="{Binding Path=ProgramTime}"/>
<!-- Level -->
<Rectangle Grid.Column="2" Grid.Row="0" Margin="10,0,0,0" Width="16" Height="16" VerticalAlignme="Top" HorizoalAlignme="Stretch" Fill="{Binding Path=Level, Converter={StaticResource MappingConverterNinjaLogLevelEnumToBrushResource}}"/>
<TextBlock Grid.Column="3" Grid.Row="0" Margin="5,0,0,0" Text="{Binding Path=LevelFriendlyName}" VerticalAlignme="Top" HorizoalAlignme="Stretch"/>
<!-- Message -->
<StackPanel Grid.Column="4" Grid.Row="0" Margin="10,0,0,0" Orieation="Horizoal" >
<TextBlock Margin="0,0,0,0" Text="{Binding Path=LogMessage}" TextWrapping="Wrap" VerticalAlignme="Top" HorizoalAlignme="Stretch"/>
<ToggleButton x:Name="ExpandExceptiooggleButton" VerticalAlignme="Top" Margin="5,0,0,0" IsChecked="False"
Coe="Show Details" Tag="Hide Details" Style="{StaticResource TextButtonStyle}"
Foreground="{StaticResource BlueBrush}" Background="{StaticResource RedBrush}"
Visibility="{Binding Path=HasException, Converter={StaticResource BoolToVisibilityConverter}}" />
</StackPanel>
<Expander IsExpanded="{Binding Path=IsChecked, ElemeName=ExpandExceptiooggleButton}" Style="{StaticResource CoeExpanderStyle}"
Margin="10,0,0,0" Grid.Column="4" Grid.Row="1">
<Border BorderBrush="{StaticResource DarkGreyBrush}" BorderThickness="1,0,0,0">
<TextBlock Text="{Binding Path=Exception}" Margin="5,0,0,0"/>
</Border>
</Expander>
</Grid>
</DataTemplate>
Можете ли вы увидеть, насколько проще определить заголовок и расширяемое тело. Если вам нужны вложенные данные, добавьте свойство Level в модель представления (вы используете MVVM, не так ли ?!), а затем создайте IValueConverter
, который возвращает маржу (т. Е. Thickness
), чтобы имитировать отступ ,
Надеюсь, это поможет, если у вас есть дополнительные вопросы, не стесняйтесь задавать.