Skip to content

Commit 486d73a

Browse files
MohammadHadi2031MohammadHadi Attarieh
andauthored
implement TreeDataGrid (#3877)
* Implement GridView support for having columns * clean up * automatically add toggle button to first column * clean up * fix style issues --------- Co-authored-by: MohammadHadi Attarieh <mhadi.atttarieh@gmail.com>
1 parent aa2bddd commit 486d73a

File tree

7 files changed

+245
-45
lines changed

7 files changed

+245
-45
lines changed

src/MainDemo.Wpf/Trees.xaml

Lines changed: 112 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
</Grid.ColumnDefinitions>
3434

3535
<Grid.RowDefinitions>
36+
<RowDefinition Height="Auto" />
37+
<RowDefinition Height="Auto" MaxHeight="450" />
3638
<RowDefinition Height="Auto" />
3739
<RowDefinition Height="Auto" MaxHeight="450" />
3840
<RowDefinition Height="Auto" />
@@ -203,20 +205,22 @@
203205
</Grid>
204206
</smtx:XamlDisplay>
205207

206-
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}" Text="Multi-Select Tree View:"
207-
Grid.Column="2"/>
208-
<smtx:XamlDisplay Grid.Row="1"
209-
Grid.Column="2"
210-
VerticalContentAlignment="Top"
211-
UniqueKey="trees_3">
208+
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}" Text="Multi-Select Tree List View:"
209+
Grid.Row="2"
210+
Grid.Column="0"
211+
Margin="0,40,0,0"/>
212+
<smtx:XamlDisplay Grid.Row="3"
213+
Grid.Column="0"
214+
VerticalContentAlignment="Top"
215+
UniqueKey="trees_3"
216+
Margin="0,75,0,20">
212217
<Grid>
213218
<materialDesign:TreeListView MinWidth="220" MaxHeight="450"
214219
ItemsSource="{Binding TreeItems}"
215220
SelectedItem="{Binding SelectedTreeItem}">
216221
<materialDesign:TreeListView.Resources>
217-
<HierarchicalDataTemplate DataType="{x:Type domain:TestItem}"
218-
ItemsSource="{Binding Items, Mode=OneTime}">
219-
<TextBlock Margin="3,2" Text="{Binding Name, Mode=OneTime}" />
222+
<HierarchicalDataTemplate DataType="{x:Type domain:TestItem}" ItemsSource="{Binding Items, Mode=OneTime}">
223+
<TextBlock VerticalAlignment="Center" Text="{Binding Name, Mode=OneTime}" />
220224
</HierarchicalDataTemplate>
221225

222226
<HierarchicalDataTemplate DataType="{x:Type domain:MovieCategory}"
@@ -231,19 +235,20 @@
231235
</DataTemplate>
232236
</materialDesign:TreeListView.Resources>
233237

234-
<!--
235-
Because Data Virtualization is enabled on this tree view by default, if you don't bind the IsExpanded property to something in the bound view model,
236-
you can loose the expanded state of items when the TreeListViewItem is recycled.
237-
238-
For more information:
239-
https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/issues/3640#issuecomment-2274086113
240-
https://learn.microsoft.com/dotnet/desktop/wpf/advanced/optimizing-performance-controls?view=netframeworkdesktop-4.8&WT.mc_id=DT-MVP-5003472
241-
-->
238+
<!--
239+
Because Data Virtualization is enabled on this tree view by default, if you don't bind the IsExpanded property to something in the bound view model,
240+
you can loose the expanded state of items when the TreeListViewItem is recycled.
241+
242+
For more information:
243+
https://github.com/MaterialDesignInXAML/MaterialDesignInXamlToolkit/issues/3640#issuecomment-2274086113
244+
https://learn.microsoft.com/dotnet/desktop/wpf/advanced/optimizing-performance-controls?view=netframeworkdesktop-4.8&WT.mc_id=DT-MVP-5003472
245+
-->
242246
<materialDesign:TreeListView.ItemContainerStyle>
243247
<Style TargetType="materialDesign:TreeListViewItem" BasedOn="{StaticResource {x:Type materialDesign:TreeListViewItem}}">
244248
<Setter Property="IsExpanded" Value="{Binding IsExpanded}" />
245249
</Style>
246250
</materialDesign:TreeListView.ItemContainerStyle>
251+
247252
</materialDesign:TreeListView>
248253
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Right">
249254
<Button Command="{Binding AddListTreeItemCommand}"
@@ -258,11 +263,95 @@
258263
</Grid>
259264
</smtx:XamlDisplay>
260265

261-
<TextBlock Grid.Row="2"
266+
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}"
267+
Text="Multi-Select Tree Grid View:"
268+
Grid.Row="2"
269+
Grid.Column="1"
270+
Margin="0,40,0,0" />
271+
<smtx:XamlDisplay Grid.Row="3"
272+
Grid.Column="1"
273+
VerticalContentAlignment="Top"
274+
UniqueKey="trees_7"
275+
Margin="0,20,0,20">
276+
<Grid>
277+
<materialDesign:TreeListView MinWidth="220"
278+
MaxHeight="450"
279+
ItemsSource="{Binding TreeItems}"
280+
SelectedItem="{Binding SelectedTreeItem}">
281+
<materialDesign:TreeListView.Resources>
282+
<HierarchicalDataTemplate DataType="{x:Type domain:TestItem}"
283+
ItemsSource="{Binding Items, Mode=OneTime}">
284+
<TextBlock VerticalAlignment="Center"
285+
Text="{Binding Name, Mode=OneTime}" />
286+
</HierarchicalDataTemplate>
287+
288+
<HierarchicalDataTemplate DataType="{x:Type domain:MovieCategory}"
289+
ItemsSource="{Binding Movies, Mode=OneTime}">
290+
<TextBlock Margin="3,2"
291+
Text="{Binding Name, Mode=OneTime}" />
292+
</HierarchicalDataTemplate>
293+
294+
<DataTemplate DataType="{x:Type domain:Movie}">
295+
<TextBlock Margin="3,2"
296+
Text="{Binding Name, Mode=OneTime}"
297+
ToolTip="{Binding Director, Mode=OneTime}" />
298+
</DataTemplate>
299+
</materialDesign:TreeListView.Resources>
300+
301+
<materialDesign:TreeListView.ItemContainerStyle>
302+
<Style TargetType="materialDesign:TreeListViewItem"
303+
BasedOn="{StaticResource {x:Type materialDesign:TreeListViewItem}}">
304+
<Setter Property="IsExpanded"
305+
Value="{Binding IsExpanded}" />
306+
</Style>
307+
</materialDesign:TreeListView.ItemContainerStyle>
308+
309+
<materialDesign:TreeListView.View>
310+
<GridView>
311+
<GridView.Columns>
312+
<GridViewColumn Width="250"
313+
Header="Name">
314+
<GridViewColumn.CellTemplate>
315+
<DataTemplate>
316+
<TextBlock VerticalAlignment="Center"
317+
Text="{Binding Name, Mode=OneTime}" />
318+
</DataTemplate>
319+
</GridViewColumn.CellTemplate>
320+
</GridViewColumn>
321+
322+
<GridViewColumn Width="100"
323+
Header="Count">
324+
<GridViewColumn.CellTemplate>
325+
<DataTemplate>
326+
<TextBlock VerticalAlignment="Center"
327+
Text="{Binding Items.Count, Mode=OneWay}" />
328+
</DataTemplate>
329+
</GridViewColumn.CellTemplate>
330+
</GridViewColumn>
331+
</GridView.Columns>
332+
</GridView>
333+
</materialDesign:TreeListView.View>
334+
</materialDesign:TreeListView>
335+
<StackPanel Orientation="Horizontal"
336+
VerticalAlignment="Bottom"
337+
HorizontalAlignment="Right">
338+
<Button Command="{Binding AddListTreeItemCommand}"
339+
ToolTip="Add an item"
340+
Content="{materialDesign:PackIcon Kind=Add}" />
341+
342+
<Button Command="{Binding RemoveListTreeItemCommand}"
343+
ToolTip="Remove selected item(s)"
344+
Content="{materialDesign:PackIcon Kind=Remove}" />
345+
346+
</StackPanel>
347+
</Grid>
348+
</smtx:XamlDisplay>
349+
350+
<TextBlock Grid.Row="4"
262351
Style="{StaticResource PageSectionTitleTextBlock}"
263352
Text="Additional node content, syntax 1" />
264353

265-
<smtx:XamlDisplay Grid.Row="3"
354+
<smtx:XamlDisplay Grid.Row="5"
266355
UniqueKey="trees_4">
267356
<TreeView>
268357
<materialDesign:TreeViewAssist.AdditionalTemplate>
@@ -305,13 +394,13 @@
305394
</TreeView>
306395
</smtx:XamlDisplay>
307396

308-
<TextBlock Grid.Row="2"
397+
<TextBlock Grid.Row="4"
309398
Grid.Column="1"
310399
Margin="32,0,0,0"
311400
Style="{StaticResource PageSectionTitleTextBlock}"
312401
Text="Additional node content, syntax 2" />
313402

314-
<smtx:XamlDisplay Grid.Row="3"
403+
<smtx:XamlDisplay Grid.Row="5"
315404
Grid.Column="1"
316405
Margin="32,0,0,0"
317406
UniqueKey="trees_5">
@@ -355,13 +444,13 @@
355444
</TreeView>
356445
</smtx:XamlDisplay>
357446

358-
<TextBlock Grid.Row="2"
447+
<TextBlock Grid.Row="4"
359448
Grid.Column="2"
360449
Margin="32,0,0,0"
361450
Style="{StaticResource PageSectionTitleTextBlock}"
362451
Text="Additional node content, showcase" />
363452

364-
<smtx:XamlDisplay Grid.Row="3"
453+
<smtx:XamlDisplay Grid.Row="5"
365454
Grid.Column="2"
366455
Margin="32,0,0,0"
367456
UniqueKey="trees_6">
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System.Globalization;
2+
using System.Windows.Data;
3+
4+
namespace MaterialDesignThemes.Wpf.Converters.Internal;
5+
6+
internal class ViewIsGridViewConverter : IValueConverter
7+
{
8+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
9+
{
10+
// Returns true if value is a GridView, otherwise false
11+
return value is GridView;
12+
}
13+
14+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
15+
{
16+
throw new NotSupportedException();
17+
}
18+
}

src/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.ListView.xaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,6 @@
193193
</Style.Triggers>
194194
</Style>
195195

196-
197-
198196
<Style x:Key="MaterialDesignListView" TargetType="{x:Type ListView}">
199197
<Style.Resources>
200198
<converters:ListViewGridViewConverter x:Key="MaterialDesignListViewItemContainerStyleConverter"

src/MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.TreeListView.xaml

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
33
xmlns:converters="clr-namespace:MaterialDesignThemes.Wpf.Converters"
4-
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf"
5-
xmlns:internal="clr-namespace:MaterialDesignThemes.Wpf.Internal">
4+
xmlns:internalConverters="clr-namespace:MaterialDesignThemes.Wpf.Converters.Internal"
5+
xmlns:internal="clr-namespace:MaterialDesignThemes.Wpf.Internal"
6+
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf">
7+
<internalConverters:ViewIsGridViewConverter x:Key="ViewIsGridViewConverter" />
68

79
<Style x:Key="MaterialDesignTreeListViewToggleButtonStyle" TargetType="{x:Type ToggleButton}">
810
<Setter Property="Background" Value="Transparent" />
11+
<Setter Property="Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource AncestorType=wpf:TreeListViewItem}}" />
912
<Setter Property="Focusable" Value="False" />
1013
<Setter Property="Height" Value="16" />
14+
<Setter Property="Margin" Value="8,0,8,0" />
1115
<Setter Property="Template">
1216
<Setter.Value>
1317
<ControlTemplate TargetType="{x:Type ToggleButton}">
@@ -78,6 +82,11 @@
7882
</Canvas>
7983
</Viewbox>
8084
</Border>
85+
<ControlTemplate.Triggers>
86+
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type wpf:TreeListViewItem}}, Path=HasItems}" Value="false">
87+
<Setter Property="Visibility" Value="Hidden" />
88+
</DataTrigger>
89+
</ControlTemplate.Triggers>
8190
</ControlTemplate>
8291
</Setter.Value>
8392
</Setter>
@@ -104,11 +113,14 @@
104113
<Setter Property="Template">
105114
<Setter.Value>
106115
<ControlTemplate TargetType="{x:Type wpf:TreeListViewItem}">
107-
<Grid>
116+
<Grid x:Name="ItemGrid">
108117
<Grid.Margin>
109118
<MultiBinding Converter="{x:Static converters:TreeListViewIndentConverter.Instance}">
110-
<Binding Path="LevelIndentSize" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type wpf:TreeListView}}" FallbackValue="16" />
111-
<Binding Path="Level" RelativeSource="{RelativeSource TemplatedParent}" />
119+
<Binding Path="LevelIndentSize"
120+
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type wpf:TreeListView}}"
121+
FallbackValue="16" />
122+
<Binding Path="Level"
123+
RelativeSource="{RelativeSource TemplatedParent}" />
112124
</MultiBinding>
113125
</Grid.Margin>
114126
<Grid.ColumnDefinitions>
@@ -167,13 +179,11 @@
167179
<ToggleButton x:Name="Expander"
168180
Width="{TemplateBinding wpf:TreeViewAssist.ExpanderSize}"
169181
Height="{TemplateBinding wpf:TreeViewAssist.ExpanderSize}"
170-
Margin="8,0,8,0"
171182
VerticalAlignment="Center"
172183
ClickMode="Press"
173184
Foreground="{TemplateBinding Foreground}"
174185
IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
175186
Style="{StaticResource MaterialDesignTreeListViewToggleButtonStyle}" />
176-
177187
<Border x:Name="MouseOverBorder"
178188
Grid.Column="1"
179189
Grid.ColumnSpan="2"
@@ -198,8 +208,18 @@
198208
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
199209
Feedback="{TemplateBinding Foreground, Converter={x:Static converters:BrushRoundConverter.Instance}}"
200210
Focusable="False"
211+
Foreground="{TemplateBinding Foreground}"
201212
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
202-
<internal:TreeListViewContentPresenter x:Name="PART_ContentPresenter" ContentSource="Content" />
213+
<Grid Margin="0,0,0,0">
214+
<internal:TreeListViewContentPresenter x:Name="PART_ContentPresenter"
215+
ContentSource="Content"
216+
Visibility="Visible" />
217+
218+
<GridViewRowPresenter x:Name="PART_GridViewRowPresenterr"
219+
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
220+
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
221+
Visibility="Collapsed" />
222+
</Grid>
203223
</wpf:Ripple>
204224
</Grid>
205225

@@ -219,9 +239,6 @@
219239
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=(wpf:TreeViewAssist.AdditionalTemplateSelector), Converter={x:Static converters:NullableToVisibilityConverter.CollapsedInstance}, Mode=OneWay}" Value="Visible">
220240
<Setter TargetName="AdditionalContentControl" Property="Visibility" Value="Visible" />
221241
</DataTrigger>
222-
<Trigger Property="HasItems" Value="false">
223-
<Setter TargetName="Expander" Property="Visibility" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(wpf:TreeViewAssist.HasNoItemsExpanderVisibility)}" />
224-
</Trigger>
225242
<Trigger Property="IsEnabled" Value="false">
226243
<Setter Property="Opacity" Value=".56" />
227244
</Trigger>
@@ -230,6 +247,12 @@
230247
<Setter TargetName="Ripple" Property="Feedback" Value="Transparent" />
231248
<Setter TargetName="SelectedBorder" Property="Visibility" Value="Collapsed" />
232249
</DataTrigger>
250+
<DataTrigger Binding="{Binding View, RelativeSource={RelativeSource AncestorType=wpf:TreeListView}, Converter={StaticResource ViewIsGridViewConverter}}" Value="True">
251+
<Setter TargetName="PART_ContentPresenter" Property="Visibility" Value="Hidden" />
252+
<Setter TargetName="PART_GridViewRowPresenterr" Property="Visibility" Value="Visible" />
253+
<Setter TargetName="Expander" Property="Visibility" Value="Collapsed" />
254+
<Setter TargetName="ItemGrid" Property="Margin" Value="0" />
255+
</DataTrigger>
233256
</ControlTemplate.Triggers>
234257
</ControlTemplate>
235258
</Setter.Value>
@@ -245,6 +268,7 @@
245268
<Setter Property="BorderBrush" Value="{x:Null}" />
246269
<Setter Property="BorderThickness" Value="0" />
247270
<Setter Property="Foreground" Value="{DynamicResource MaterialDesign.Brush.Foreground}" />
271+
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
248272
<Setter Property="Padding" Value="1" />
249273
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
250274
<Setter Property="ScrollViewer.PanningMode" Value="Both" />
@@ -257,6 +281,7 @@
257281
BorderThickness="{TemplateBinding BorderThickness}"
258282
SnapsToDevicePixels="true">
259283
<ScrollViewer x:Name="PART_ScrollViewer"
284+
Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}"
260285
wpf:ScrollViewerAssist.IgnorePadding="{Binding Path=(wpf:ScrollViewerAssist.IgnorePadding), RelativeSource={RelativeSource TemplatedParent}}"
261286
wpf:ScrollViewerAssist.PaddingMode="{Binding Path=(wpf:ScrollViewerAssist.PaddingMode), RelativeSource={RelativeSource TemplatedParent}}"
262287
Padding="{TemplateBinding Padding}"

0 commit comments

Comments
 (0)