fix: force re-create the tree instead of only rebuild the source for the tree (#157)

This commit is contained in:
leo 2024-06-02 14:06:27 +08:00
parent 9d88ae466f
commit f1f54bf6fe
2 changed files with 62 additions and 55 deletions

View file

@ -3,41 +3,33 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:SourceGit.Models" xmlns:m="using:SourceGit.Models"
xmlns:vm="using:SourceGit.ViewModels"
xmlns:v="using:SourceGit.Views" xmlns:v="using:SourceGit.Views"
xmlns:c="using:SourceGit.Converters" xmlns:c="using:SourceGit.Converters"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.ChangeCollectionView" x:Class="SourceGit.Views.ChangeCollectionView"
x:Name="me"> x:Name="ThisControl">
<TreeDataGrid x:Name="tree" <UserControl.Resources>
AutoDragDropRows="False" <DataTemplate x:Key="TreeModeTemplate" DataType="m:FileTreeNode">
ShowColumnHeaders="False" <Grid HorizontalAlignment="Stretch" Height="24" ColumnDefinitions="Auto,*">
CanUserResizeColumns="False" <Path Grid.Column="0" Classes="folder_icon" Width="14" Height="14" Margin="0,2,0,0" IsVisible="{Binding IsFolder}" Fill="Goldenrod" VerticalAlignment="Center"/>
CanUserSortColumns="False" <v:ChangeStatusIcon Grid.Column="0" Width="14" Height="14" IsWorkingCopyChange="{Binding #ThisControl.IsWorkingCopyChange}" Change="{Binding Backend}" IsVisible="{Binding !IsFolder}"/>
ScrollViewer.BringIntoViewOnFocusChange="True"> <TextBlock Grid.Column="1" Classes="monospace" Text="{Binding FullPath, Converter={x:Static c:PathConverters.PureFileName}}" Margin="6,0,0,0"/>
<TreeDataGrid.Resources> </Grid>
<DataTemplate x:Key="TreeModeTemplate" DataType="m:FileTreeNode"> </DataTemplate>
<Grid HorizontalAlignment="Stretch" Height="24" ColumnDefinitions="Auto,*">
<Path Grid.Column="0" Classes="folder_icon" Width="14" Height="14" Margin="0,2,0,0" IsVisible="{Binding IsFolder}" Fill="Goldenrod" VerticalAlignment="Center"/>
<v:ChangeStatusIcon Grid.Column="0" Width="14" Height="14" IsWorkingCopyChange="{Binding #me.IsWorkingCopyChange}" Change="{Binding Backend}" IsVisible="{Binding !IsFolder}"/>
<TextBlock Grid.Column="1" Classes="monospace" Text="{Binding FullPath, Converter={x:Static c:PathConverters.PureFileName}}" Margin="6,0,0,0"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="ListModeTemplate" DataType="m:Change"> <DataTemplate x:Key="ListModeTemplate" DataType="m:Change">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<v:ChangeStatusIcon Width="14" Height="14" IsWorkingCopyChange="{Binding #me.IsWorkingCopyChange}" Change="{Binding}" Margin="4,0,0,0"/> <v:ChangeStatusIcon Width="14" Height="14" IsWorkingCopyChange="{Binding #ThisControl.IsWorkingCopyChange}" Change="{Binding}" Margin="4,0,0,0"/>
<TextBlock Classes="monospace" Text="{Binding Path}" Margin="4,0"/> <TextBlock Classes="monospace" Text="{Binding Path}" Margin="4,0"/>
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
<DataTemplate x:Key="GridModeTemplate" DataType="m:Change"> <DataTemplate x:Key="GridModeTemplate" DataType="m:Change">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<v:ChangeStatusIcon Width="14" Height="14" IsWorkingCopyChange="{Binding #me.IsWorkingCopyChange}" Change="{Binding}" Margin="4,0,0,0"/> <v:ChangeStatusIcon Width="14" Height="14" IsWorkingCopyChange="{Binding #ThisControl.IsWorkingCopyChange}" Change="{Binding}" Margin="4,0,0,0"/>
<TextBlock Classes="monospace" Text="{Binding Path, Converter={x:Static c:PathConverters.PureFileName}}" Margin="4,0"/> <TextBlock Classes="monospace" Text="{Binding Path, Converter={x:Static c:PathConverters.PureFileName}}" Margin="4,0"/>
<TextBlock Classes="monospace" Text="{Binding Path, Converter={x:Static c:PathConverters.PureDirectoryName}}" Foreground="{DynamicResource Brush.FG2}"/> <TextBlock Classes="monospace" Text="{Binding Path, Converter={x:Static c:PathConverters.PureDirectoryName}}" Foreground="{DynamicResource Brush.FG2}"/>
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</TreeDataGrid.Resources> </UserControl.Resources>
</TreeDataGrid>
</UserControl> </UserControl>

View file

@ -4,6 +4,7 @@ using System.Collections.Generic;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Models.TreeDataGrid; using Avalonia.Controls.Models.TreeDataGrid;
using Avalonia.Controls.Templates;
using Avalonia.Interactivity; using Avalonia.Interactivity;
namespace SourceGit.Views namespace SourceGit.Views
@ -78,11 +79,10 @@ namespace SourceGit.Views
private void UpdateSource() private void UpdateSource()
{ {
if (tree.Source is IDisposable disposable) if (Content is TreeDataGrid tree && tree.Source is IDisposable disposable)
{
disposable.Dispose(); disposable.Dispose();
tree.Source = null;
} Content = null;
var changes = Changes; var changes = Changes;
if (changes == null) if (changes == null)
@ -92,12 +92,13 @@ namespace SourceGit.Views
if (viewMode == Models.ChangeViewMode.Tree) if (viewMode == Models.ChangeViewMode.Tree)
{ {
var filetree = Models.FileTreeNode.Build(changes, true); var filetree = Models.FileTreeNode.Build(changes, true);
var template = this.FindResource("TreeModeTemplate") as IDataTemplate;
var source = new HierarchicalTreeDataGridSource<Models.FileTreeNode>(filetree) var source = new HierarchicalTreeDataGridSource<Models.FileTreeNode>(filetree)
{ {
Columns = Columns =
{ {
new HierarchicalExpanderColumn<Models.FileTreeNode>( new HierarchicalExpanderColumn<Models.FileTreeNode>(
new TemplateColumn<Models.FileTreeNode>(null, "TreeModeTemplate", null, GridLength.Auto), new TemplateColumn<Models.FileTreeNode>(null, template, null, GridLength.Auto),
x => x.Children, x => x.Children,
x => x.Children.Count > 0, x => x.Children.Count > 0,
x => x.IsExpanded) x => x.IsExpanded)
@ -111,24 +112,25 @@ namespace SourceGit.Views
{ {
if (!_isSelecting && s is Models.TreeDataGridSelectionModel<Models.FileTreeNode> model) if (!_isSelecting && s is Models.TreeDataGridSelectionModel<Models.FileTreeNode> model)
{ {
var selection = new List<Models.Change>(); var selected = new List<Models.Change>();
foreach (var c in model.SelectedItems) foreach (var c in model.SelectedItems)
CollectChangesInNode(selection, c); CollectChangesInNode(selected, c);
_isSelecting = true; _isSelecting = true;
SetCurrentValue(SelectedChangesProperty, selection); SetCurrentValue(SelectedChangesProperty, selected);
_isSelecting = false; _isSelecting = false;
} }
}; };
source.Selection = selection; source.Selection = selection;
tree.Source = source; CreateTreeDataGrid(source);
} }
else if (viewMode == Models.ChangeViewMode.List) else if (viewMode == Models.ChangeViewMode.List)
{ {
var template = this.FindResource("ListModeTemplate") as IDataTemplate;
var source = new FlatTreeDataGridSource<Models.Change>(changes) var source = new FlatTreeDataGridSource<Models.Change>(changes)
{ {
Columns = { new TemplateColumn<Models.Change>(null, "ListModeTemplate", null, GridLength.Auto) } Columns = { new TemplateColumn<Models.Change>(null, template, null, GridLength.Auto) }
}; };
var selection = new Models.TreeDataGridSelectionModel<Models.Change>(source, null); var selection = new Models.TreeDataGridSelectionModel<Models.Change>(source, null);
@ -138,24 +140,25 @@ namespace SourceGit.Views
{ {
if (!_isSelecting && s is Models.TreeDataGridSelectionModel<Models.Change> model) if (!_isSelecting && s is Models.TreeDataGridSelectionModel<Models.Change> model)
{ {
var selection = new List<Models.Change>(); var selected = new List<Models.Change>();
foreach (var c in model.SelectedItems) foreach (var c in model.SelectedItems)
selection.Add(c); selected.Add(c);
_isSelecting = true; _isSelecting = true;
SetCurrentValue(SelectedChangesProperty, selection); SetCurrentValue(SelectedChangesProperty, selected);
_isSelecting = false; _isSelecting = false;
} }
}; };
source.Selection = selection; source.Selection = selection;
tree.Source = source; CreateTreeDataGrid(source);
} }
else else
{ {
var template = this.FindResource("GridModeTemplate") as IDataTemplate;
var source = new FlatTreeDataGridSource<Models.Change>(changes) var source = new FlatTreeDataGridSource<Models.Change>(changes)
{ {
Columns = { new TemplateColumn<Models.Change>(null, "GridModeTemplate", null, GridLength.Auto) }, Columns = { new TemplateColumn<Models.Change>(null, template, null, GridLength.Auto) },
}; };
var selection = new Models.TreeDataGridSelectionModel<Models.Change>(source, null); var selection = new Models.TreeDataGridSelectionModel<Models.Change>(source, null);
@ -165,24 +168,28 @@ namespace SourceGit.Views
{ {
if (!_isSelecting && s is Models.TreeDataGridSelectionModel<Models.Change> model) if (!_isSelecting && s is Models.TreeDataGridSelectionModel<Models.Change> model)
{ {
var selection = new List<Models.Change>(); var selected = new List<Models.Change>();
foreach (var c in model.SelectedItems) foreach (var c in model.SelectedItems)
selection.Add(c); selected.Add(c);
_isSelecting = true; _isSelecting = true;
SetCurrentValue(SelectedChangesProperty, selection); SetCurrentValue(SelectedChangesProperty, selected);
_isSelecting = false; _isSelecting = false;
} }
}; };
source.Selection = selection; source.Selection = selection;
tree.Source = source; CreateTreeDataGrid(source);
} }
} }
private void UpdateSelected() private void UpdateSelected()
{ {
if (_isSelecting || tree.Source == null) if (_isSelecting || Content == null)
return;
var tree = Content as TreeDataGrid;
if (tree == null)
return; return;
_isSelecting = true; _isSelecting = true;
@ -212,17 +219,25 @@ namespace SourceGit.Views
CollectSelectedNodeByChange(nodes, node as Models.FileTreeNode, set); CollectSelectedNodeByChange(nodes, node as Models.FileTreeNode, set);
if (nodes.Count == 0) if (nodes.Count == 0)
{
treeSelection.Clear(); treeSelection.Clear();
}
else else
{
treeSelection.Select(nodes); treeSelection.Select(nodes);
}
} }
_isSelecting = false; _isSelecting = false;
} }
private void CreateTreeDataGrid(ITreeDataGridSource source)
{
Content = new TreeDataGrid()
{
AutoDragDropRows = false,
ShowColumnHeaders = false,
CanUserResizeColumns = false,
CanUserSortColumns = false,
Source = source,
};
}
private void CollectChangesInNode(List<Models.Change> outs, Models.FileTreeNode node) private void CollectChangesInNode(List<Models.Change> outs, Models.FileTreeNode node)
{ {
if (node.IsFolder) if (node.IsFolder)