ux: use ListBox with VirtualizingStackPanel instead of DataGrid since height of DataGridRow is not equal with the RowHeight value

This commit is contained in:
leo 2024-08-20 16:53:59 +08:00
parent d4a9343eaf
commit 9844043c7f
No known key found for this signature in database
6 changed files with 180 additions and 254 deletions

View file

@ -706,6 +706,58 @@
<Setter Property="Opacity" Value="1"/> <Setter Property="Opacity" Value="1"/>
</Style> </Style>
<Style Selector="ListBox.repo_left_content_list">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ItemsPanel">
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</Setter>
<Style Selector="^ ListBoxItem">
<Setter Property="Height" Value="24"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="CornerRadius" Value="4"/>
<Setter Property="Template">
<ControlTemplate>
<Grid>
<Border Name="PART_Background"
Background="Transparent"
CornerRadius="{TemplateBinding CornerRadius}"
Opacity="0"/>
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Stretch" />
</Grid>
</ControlTemplate>
</Setter>
</Style>
</Style>
<Style Selector="Grid.repository_leftpanel ListBox.repo_left_content_list ListBoxItem:pointerover /template/ Border#PART_Background">
<Setter Property="Background" Value="{DynamicResource Brush.AccentHovered}" />
<Setter Property="Opacity" Value=".5"/>
</Style>
<Style Selector="Grid.repository_leftpanel ListBox.repo_left_content_list ListBoxItem:selected /template/ Border#PART_Background">
<Setter Property="Background" Value="{DynamicResource Brush.AccentHovered}" />
<Setter Property="Opacity" Value="1"/>
</Style>
<Style Selector="Grid.repository_leftpanel:focus-within ListBox.repo_left_content_list ListBoxItem:selected /template/ Border#PART_Background">
<Setter Property="Background" Value="{DynamicResource Brush.Accent}" />
<Setter Property="Opacity" Value=".65"/>
</Style>
<Style Selector="Grid.repository_leftpanel:focus-within ListBox.repo_left_content_list ListBoxItem:selected:pointerover /template/ Border#PART_Background">
<Setter Property="Background" Value="{DynamicResource Brush.Accent}" />
<Setter Property="Opacity" Value=".8"/>
</Style>
<Style Selector="ContextMenu"> <Style Selector="ContextMenu">
<Setter Property="HorizontalOffset" Value="-4"/> <Setter Property="HorizontalOffset" Value="-4"/>
<Setter Property="VerticalOffset" Value="-4"/> <Setter Property="VerticalOffset" Value="-4"/>

View file

@ -8,50 +8,26 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SourceGit.Views.BranchTree" x:Class="SourceGit.Views.BranchTree"
x:Name="ThisControl"> x:Name="ThisControl">
<DataGrid x:Name="BranchesPresenter" <ListBox x:Name="BranchesPresenter"
Classes="repo_left_content_list"
ItemsSource="{Binding #ThisControl.Rows}" ItemsSource="{Binding #ThisControl.Rows}"
Background="Transparent" SelectionMode="Multiple"
RowHeight="24"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserSortColumns="False"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
HeadersVisibility="None"
SelectionChanged="OnNodesSelectionChanged" SelectionChanged="OnNodesSelectionChanged"
ContextRequested="OnTreeContextRequested"> ContextRequested="OnTreeContextRequested">
<DataGrid.Styles> <ListBox.ItemsPanel>
<Style Selector="DataGridRow" x:DataType="vm:BranchTreeNode"> <ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.Styles>
<Style Selector="ListBoxItem" x:DataType="vm:BranchTreeNode">
<Setter Property="CornerRadius" Value="{Binding CornerRadius}"/> <Setter Property="CornerRadius" Value="{Binding CornerRadius}"/>
<Setter Property="Height" Value="24"/>
</Style> </Style>
</ListBox.Styles>
<Style Selector="DataGridRow /template/ Border#RowBorder"> <ListBox.ItemTemplate>
<Setter Property="ClipToBounds" Value="True" /> <DataTemplate DataType="vm:BranchTreeNode">
</Style>
<Style Selector="Grid.repository_leftpanel DataGridRow:pointerover /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.AccentHovered}" />
<Setter Property="Opacity" Value=".5"/>
</Style>
<Style Selector="Grid.repository_leftpanel DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.AccentHovered}" />
<Setter Property="Opacity" Value="1"/>
</Style>
<Style Selector="Grid.repository_leftpanel:focus-within DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}" />
<Setter Property="Opacity" Value=".65"/>
</Style>
<Style Selector="Grid.repository_leftpanel:focus-within DataGridRow:selected:pointerover /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}" />
<Setter Property="Opacity" Value=".8"/>
</Style>
</DataGrid.Styles>
<DataGrid.Columns>
<DataGridTemplateColumn Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="vm:BranchTreeNode">
<Grid Height="24" <Grid Height="24"
Margin="{Binding Depth, Converter={x:Static c:IntConverters.ToTreeMargin}}" Margin="{Binding Depth, Converter={x:Static c:IntConverters.ToTreeMargin}}"
ColumnDefinitions="16,*" ColumnDefinitions="16,*"
@ -103,9 +79,7 @@
</Grid> </Grid>
</Grid> </Grid>
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </ListBox.ItemTemplate>
</DataGridTemplateColumn> </ListBox>
</DataGrid.Columns>
</DataGrid>
</UserControl> </UserControl>

View file

@ -240,70 +240,31 @@
</Button> </Button>
</Grid> </Grid>
</ToggleButton> </ToggleButton>
<DataGrid Grid.Row="7" <ListBox Grid.Row="7"
x:Name="SubmoduleList" x:Name="SubmoduleList"
Height="0" Height="0"
Margin="8,0,4,0" Margin="8,0,4,0"
Background="Transparent" Classes="repo_left_content_list"
ItemsSource="{Binding Submodules}" ItemsSource="{Binding Submodules}"
SelectionMode="Single" SelectionMode="Single"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserSortColumns="False"
IsReadOnly="True"
HeadersVisibility="None"
Focusable="False"
RowHeight="24"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
ContextRequested="OnSubmoduleContextRequested" ContextRequested="OnSubmoduleContextRequested"
DoubleTapped="OnDoubleTappedSubmodule" DoubleTapped="OnDoubleTappedSubmodule"
PropertyChanged="OnLeftSidebarDataGridPropertyChanged" PropertyChanged="OnLeftSidebarDataGridPropertyChanged"
IsVisible="{Binding IsSubmoduleGroupExpanded, Mode=OneWay}"> IsVisible="{Binding IsSubmoduleGroupExpanded, Mode=OneWay}">
<DataGrid.Styles> <ListBox.ItemTemplate>
<Style Selector="DataGridRow"> <DataTemplate DataType="m:Submodule">
<Setter Property="CornerRadius" Value="4" /> <Grid ColumnDefinitions="Auto,*,8">
<Setter Property="Height" Value="24"/> <Path Grid.Column="0" Width="10" Height="10" Margin="8,0" Data="{StaticResource Icons.Submodule}"/>
</Style> <TextBlock Grid.Column="1" Text="{Binding Path}" ClipToBounds="True" Classes="primary" TextTrimming="CharacterEllipsis"/>
<Path Grid.Column="2"
<Style Selector="DataGridRow /template/ Border#RowBorder">
<Setter Property="ClipToBounds" Value="True" />
</Style>
<Style Selector="DataGridRow:pointerover /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.AccentHovered}" />
</Style>
<Style Selector="DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}" />
</Style>
</DataGrid.Styles>
<DataGrid.Columns>
<DataGridTemplateColumn Header="ICON">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Path Width="10" Height="10" Margin="8,0" Data="{StaticResource Icons.Submodule}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="NAME">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid Background="Transparent" Margin="0,0,4,0" ColumnDefinitions="*,8">
<TextBlock Grid.Column="0" Text="{Binding Path}" ClipToBounds="True" Classes="primary" TextTrimming="CharacterEllipsis"/>
<Path Grid.Column="1"
Width="8" Height="8" Width="8" Height="8"
Fill="Goldenrod" Fill="Goldenrod"
Data="{StaticResource Icons.Modified}" Data="{StaticResource Icons.Modified}"
IsVisible="{Binding IsDirty}"/> IsVisible="{Binding IsDirty}"/>
</Grid> </Grid>
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </ListBox.ItemTemplate>
</DataGridTemplateColumn> </ListBox>
</DataGrid.Columns>
</DataGrid>
<!-- Worktrees --> <!-- Worktrees -->
<ToggleButton Grid.Row="8" Classes="group_expander" IsChecked="{Binding IsWorktreeGroupExpanded, Mode=TwoWay}"> <ToggleButton Grid.Row="8" Classes="group_expander" IsChecked="{Binding IsWorktreeGroupExpanded, Mode=TwoWay}">
@ -329,74 +290,30 @@
</Button> </Button>
</Grid> </Grid>
</ToggleButton> </ToggleButton>
<DataGrid Grid.Row="9" <ListBox Grid.Row="9"
x:Name="WorktreeList" x:Name="WorktreeList"
Height="0" Height="0"
Margin="8,0,4,0" Margin="8,0,4,0"
Background="Transparent" Classes="repo_left_content_list"
ItemsSource="{Binding Worktrees}" ItemsSource="{Binding Worktrees}"
SelectionMode="Single" SelectionMode="Single"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserSortColumns="False"
IsReadOnly="True"
HeadersVisibility="None"
Focusable="False"
RowHeight="24"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
ContextRequested="OnWorktreeContextRequested" ContextRequested="OnWorktreeContextRequested"
DoubleTapped="OnDoubleTappedWorktree" DoubleTapped="OnDoubleTappedWorktree"
PropertyChanged="OnLeftSidebarDataGridPropertyChanged" PropertyChanged="OnLeftSidebarDataGridPropertyChanged"
IsVisible="{Binding IsWorktreeGroupExpanded, Mode=OneWay}"> IsVisible="{Binding IsWorktreeGroupExpanded, Mode=OneWay}">
<DataGrid.Styles> <ListBox.ItemTemplate>
<Style Selector="DataGridRow"> <DataTemplate DataType="m:Worktree">
<Setter Property="CornerRadius" Value="4"/> <Grid ColumnDefinitions="Auto,*,22">
<Setter Property="Height" Value="24"/> <Path Grid.Column="0" Width="10" Height="10" Margin="8,0,0,0" Data="{StaticResource Icons.Worktree}"/>
</Style> <TextBlock Grid.Column="1" Classes="primary" Margin="8,0,0,0" TextTrimming="CharacterEllipsis">
<Style Selector="DataGridRow /template/ Border#RowBorder">
<Setter Property="ClipToBounds" Value="True" />
</Style>
<Style Selector="DataGridRow:pointerover /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.AccentHovered}" />
</Style>
<Style Selector="DataGridRow:selected /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource Brush.Accent}" />
</Style>
</DataGrid.Styles>
<DataGrid.Columns>
<DataGridTemplateColumn Header="ICON">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Path Width="10" Height="10" Margin="8,0,0,0" Data="{StaticResource Icons.Worktree}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Width="*" Header="FullPath">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Classes="primary" Margin="8,0,0,0" TextTrimming="CharacterEllipsis">
<Run Text="{Binding FullPath}"/> <Run Text="{Binding FullPath}"/>
<Run Text="{Binding Name}" Foreground="{DynamicResource Brush.FG2}"/> <Run Text="{Binding Name}" Foreground="{DynamicResource Brush.FG2}"/>
</TextBlock> </TextBlock>
<Path Grid.Column="2" Width="10" Height="10" Margin="4,0,0,0" Data="{StaticResource Icons.Lock}" Fill="{DynamicResource Brush.FG2}" IsVisible="{Binding IsLocked}"/>
</Grid>
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </ListBox.ItemTemplate>
</DataGridTemplateColumn> </ListBox>
<DataGridTemplateColumn Header="FullPath">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Path Width="10" Height="10" Margin="4,0,8,0" Data="{StaticResource Icons.Lock}" Fill="{DynamicResource Brush.FG2}" IsVisible="{Binding IsLocked}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid> </Grid>
</Grid> </Grid>

View file

@ -200,7 +200,7 @@ namespace SourceGit.Views
private void OnSubmoduleContextRequested(object sender, ContextRequestedEventArgs e) private void OnSubmoduleContextRequested(object sender, ContextRequestedEventArgs e)
{ {
if (sender is DataGrid { SelectedItem: Models.Submodule submodule } grid && DataContext is ViewModels.Repository repo) if (sender is ListBox { SelectedItem: Models.Submodule submodule } grid && DataContext is ViewModels.Repository repo)
{ {
var menu = repo.CreateContextMenuForSubmodule(submodule.Path); var menu = repo.CreateContextMenuForSubmodule(submodule.Path);
grid.OpenContextMenu(menu); grid.OpenContextMenu(menu);
@ -211,7 +211,7 @@ namespace SourceGit.Views
private void OnDoubleTappedSubmodule(object sender, TappedEventArgs e) private void OnDoubleTappedSubmodule(object sender, TappedEventArgs e)
{ {
if (sender is DataGrid { SelectedItem: Models.Submodule submodule } && DataContext is ViewModels.Repository repo) if (sender is ListBox { SelectedItem: Models.Submodule submodule } && DataContext is ViewModels.Repository repo)
{ {
repo.OpenSubmodule(submodule.Path); repo.OpenSubmodule(submodule.Path);
} }
@ -221,7 +221,7 @@ namespace SourceGit.Views
private void OnWorktreeContextRequested(object sender, ContextRequestedEventArgs e) private void OnWorktreeContextRequested(object sender, ContextRequestedEventArgs e)
{ {
if (sender is DataGrid { SelectedItem: Models.Worktree worktree } grid && DataContext is ViewModels.Repository repo) if (sender is ListBox { SelectedItem: Models.Worktree worktree } grid && DataContext is ViewModels.Repository repo)
{ {
var menu = repo.CreateContextMenuForWorktree(worktree); var menu = repo.CreateContextMenuForWorktree(worktree);
grid.OpenContextMenu(menu); grid.OpenContextMenu(menu);
@ -232,7 +232,7 @@ namespace SourceGit.Views
private void OnDoubleTappedWorktree(object sender, TappedEventArgs e) private void OnDoubleTappedWorktree(object sender, TappedEventArgs e)
{ {
if (sender is DataGrid { SelectedItem: Models.Worktree worktree } && DataContext is ViewModels.Repository repo) if (sender is ListBox { SelectedItem: Models.Worktree worktree } && DataContext is ViewModels.Repository repo)
{ {
repo.OpenWorktree(worktree); repo.OpenWorktree(worktree);
} }
@ -242,7 +242,7 @@ namespace SourceGit.Views
private void OnLeftSidebarDataGridPropertyChanged(object _, AvaloniaPropertyChangedEventArgs e) private void OnLeftSidebarDataGridPropertyChanged(object _, AvaloniaPropertyChangedEventArgs e)
{ {
if (e.Property == DataGrid.ItemsSourceProperty || e.Property == DataGrid.IsVisibleProperty) if (e.Property == ListBox.ItemsSourceProperty || e.Property == ListBox.IsVisibleProperty)
UpdateLeftSidebarLayout(); UpdateLeftSidebarLayout();
} }
@ -266,8 +266,8 @@ namespace SourceGit.Views
var remoteBranchRows = vm.IsRemoteGroupExpanded ? RemoteBranchTree.Rows.Count : 0; var remoteBranchRows = vm.IsRemoteGroupExpanded ? RemoteBranchTree.Rows.Count : 0;
var desiredBranches = (localBranchRows + remoteBranchRows) * 24.0; var desiredBranches = (localBranchRows + remoteBranchRows) * 24.0;
var desiredTag = vm.IsTagGroupExpanded ? 24.0 * TagsList.Rows : 0; var desiredTag = vm.IsTagGroupExpanded ? 24.0 * TagsList.Rows : 0;
var desiredSubmodule = vm.IsSubmoduleGroupExpanded ? SubmoduleList.RowHeight * vm.Submodules.Count : 0; var desiredSubmodule = vm.IsSubmoduleGroupExpanded ? 24.0 * vm.Submodules.Count : 0;
var desiredWorktree = vm.IsWorktreeGroupExpanded ? WorktreeList.RowHeight * vm.Worktrees.Count : 0; var desiredWorktree = vm.IsWorktreeGroupExpanded ? 24.0 * vm.Worktrees.Count : 0;
var desiredOthers = desiredTag + desiredSubmodule + desiredWorktree; var desiredOthers = desiredTag + desiredSubmodule + desiredWorktree;
var hasOverflow = (desiredBranches + desiredOthers > leftHeight); var hasOverflow = (desiredBranches + desiredOthers > leftHeight);

View file

@ -8,29 +8,10 @@
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.TagsView"> x:Class="SourceGit.Views.TagsView">
<UserControl.Styles>
<Style Selector="ListBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ItemsPanel">
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</Setter>
</Style>
<Style Selector="ListBoxItem">
<Setter Property="Height" Value="24"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="CornerRadius" Value="4"/>
</Style>
</UserControl.Styles>
<UserControl.DataTemplates> <UserControl.DataTemplates>
<DataTemplate DataType="vm:TagCollectionAsTree"> <DataTemplate DataType="vm:TagCollectionAsTree">
<ListBox ItemsSource="{Binding Rows}" <ListBox Classes="repo_left_content_list"
ItemsSource="{Binding Rows}"
SelectionMode="Single" SelectionMode="Single"
SelectionChanged="OnRowSelectionChanged"> SelectionChanged="OnRowSelectionChanged">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
@ -70,7 +51,8 @@
</DataTemplate> </DataTemplate>
<DataTemplate DataType="vm:TagCollectionAsList"> <DataTemplate DataType="vm:TagCollectionAsList">
<ListBox ItemsSource="{Binding Tags}" <ListBox Classes="repo_left_content_list"
ItemsSource="{Binding Tags}"
SelectionMode="Single" SelectionMode="Single"
SelectionChanged="OnRowSelectionChanged"> SelectionChanged="OnRowSelectionChanged">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>

View file

@ -282,6 +282,7 @@ namespace SourceGit.Views
var tags = Tags; var tags = Tags;
if (tags == null || tags.Count == 0) if (tags == null || tags.Count == 0)
{ {
Rows = 0;
Content = null; Content = null;
return; return;
} }