Use Generated NavBarItems.
MODIFY
WalletWasabi.Fluent/App.xaml
WalletWasabi.Fluent/App.xaml
<StyleInclude Source="avares://WalletWasabi.Fluent/Icons/Icons.xaml" />
<StyleInclude Source="avares://WalletWasabi.Fluent/Styles/Styles.xaml" />
<StyleInclude Source="avares://WalletWasabi.Fluent/Controls/NavBarItem.xaml" />
+ <StyleInclude Source="avares://WalletWasabi.Fluent/Controls/NavBarTreeItem.xaml" />
</Application.Styles>
</Application>

MODIFY
WalletWasabi.Fluent/Controls/NavBarItem.cs
WalletWasabi.Fluent/Controls/NavBarItem.cs
@@ -5,48 +5,14 @@ using Avalonia.Controls.Primitives;
namespace WalletWasabi.Fluent.Controls
{
- /// <summary>
- /// Template class for items to be displayed in the sidebar.
- /// </summary>
- public class NavBarItem : TemplatedControl
+ public class NavBarItem : ListBoxItem
{
- /// <summary>
- /// Defines the <see cref="IsSelected"/> property.
- /// </summary>
- public static readonly StyledProperty<bool> IsSelectedProperty =
- AvaloniaProperty.Register<NavBarItem, bool>(nameof(IsSelected));
-
- /// <summary>
- /// Defines the <see cref="Icon"/> property.
- /// </summary>
public static readonly StyledProperty<IconElement> IconProperty =
AvaloniaProperty.Register<NavBarItem, IconElement>(nameof(Icon));
- /// <summary>
- /// Defines the <see cref="Header"/> property.
- /// </summary>
public static readonly StyledProperty<string> HeaderProperty =
AvaloniaProperty.Register<NavBarItem, string>(nameof(Header));
- /// <summary>
- /// Initializes the static members of the <see cref="NavBarItem"/> class.
- /// </summary>
- static NavBarItem()
- {
- SelectableMixin.Attach<NavBarItem>(IsSelectedProperty);
- PressedMixin.Attach<NavBarItem>();
- FocusableProperty.OverrideDefaultValue<NavBarItem>(true);
- }
-
- /// <summary>
- /// Gets or sets the selection state of the item.
- /// </summary>
- public bool IsSelected
- {
- get => GetValue(IsSelectedProperty);
- set => SetValue(IsSelectedProperty, value);
- }
-
/// <summary>
/// The icon to be shown beside the header text of the item.
/// </summary>

MODIFY
WalletWasabi.Fluent/Controls/NavBarItem.xaml
WalletWasabi.Fluent/Controls/NavBarItem.xaml
<Setter Property="Padding" Value="{StaticResource ListBoxItemPadding}" />
<Setter Property="Template">
<ControlTemplate>
- <Border x:Name="LayoutRoot" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}">
<Panel>
<Border x:Name="Indicator" BorderThickness="2 0 0 0" />
- <Rectangle x:Name="PressedBackground" IsHitTestVisible="False" />
- <Border Name="PART_ContentPresenter"
+ <ContentPresenter Name="PART_ContentPresenter"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
- Padding="{TemplateBinding Padding}">
- <Panel>
- <Panel Width="45" HorizontalAlignment="Left">
- <ContentPresenter HorizontalAlignment="Left" Content="{TemplateBinding Icon}" />
- </Panel>
- <TextBlock Text="{TemplateBinding Header}" Margin="35 0 0 0" />
+ ContentTemplate="{TemplateBinding ContentTemplate}"
+ Content="{TemplateBinding Content}"
+ Padding="{TemplateBinding Padding}"
+ VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
+ HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Panel>
- </Border>
- </Panel>
- </Border>
</ControlTemplate>
</Setter>
</Style>
- <Style Selector="c|NavBarItem /template/ ContentPresenter">
+ <Style Selector="c|NavBarItem /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="TextBlock.FontWeight" Value="Normal" />
<Setter Property="TextBlock.FontSize" Value="{DynamicResource ControlContentThemeFontSize}" />
</Style>
<!-- Disabled State -->
- <Style Selector="c|NavBarItem:disabled /template/ ContentPresenter">
+ <Style Selector="c|NavBarItem:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SystemControlDisabledBaseMediumLowBrush}"/>
</Style>
<!-- PointerOver State -->
- <Style Selector="c|NavBarItem:pointerover /template/ ContentPresenter">
+ <Style Selector="c|NavBarItem:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SystemControlHighlightAltBaseHighBrush}"/>
</Style>
- <Style Selector="c|NavBarItem:pointerover /template/ Rectangle#PressedBackground">
- <Setter Property="Fill" Value="{DynamicResource SystemControlHighlightListLowBrush}"/>
+ <Style Selector="c|NavBarItem:pointerover /template/ ContentPresenter#PART_ContentPresenter">
+ <Setter Property="Background" Value="{DynamicResource SystemControlHighlightListLowBrush}"/>
</Style>
<!-- Pressed State -->
<Style Selector="c|NavBarItem:pressed /template/ Border#Indicator">
<Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColorLight1}"/>
</Style>
- <Style Selector="c|NavBarItem:pressed /template/ ContentPresenter">
+ <Style Selector="c|NavBarItem:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SystemControlHighlightAltBaseHighBrush}"/>
</Style>
<Style Selector="c|NavBarItem">
<Style Selector="c|NavBarItem:selected /template/ Border#Indicator">
<Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColor}"/>
</Style>
- <Style Selector="c|NavBarItem:selected /template/ ContentPresenter">
+ <Style Selector="c|NavBarItem:selected /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SystemControlHighlightAltBaseHighBrush}"/>
</Style>
<!-- Selected Unfocused State -->
- <Style Selector="c|NavBarItem:selected:not(:focus) /template/ ContentPresenter">
+ <Style Selector="c|NavBarItem:selected:not(:focus) /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SystemControlHighlightAltBaseHighBrush}"/>
</Style>
<Style Selector="c|NavBarItem:selected:pointerover /template/ Border">
<Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColor}"/>
</Style>
- <Style Selector="c|NavBarItem:selected:pointerover /template/ ContentPresenter">
+ <Style Selector="c|NavBarItem:selected:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SystemControlHighlightAltBaseHighBrush}"/>
</Style>
<Style Selector="c|NavBarItem:selected:pressed /template/ Border">
<Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColorLight1}"/>
</Style>
- <Style Selector="c|NavBarItem:selected:pressed /template/ ContentPresenter">
+ <Style Selector="c|NavBarItem:selected:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource SystemControlHighlightAltBaseHighBrush}"/>
</Style>
</Styles>
\ No newline at end of file

ADD
WalletWasabi.Fluent/Controls/NavBarListBox.cs
+using Avalonia.Controls;
+using Avalonia.Controls.Generators;
+using Avalonia.Styling;
+using System;
+
+namespace WalletWasabi.Fluent.Controls
+{
+ public class NavBarListBox : ListBox, IStyleable
+ {
+ Type IStyleable.StyleKey => typeof(ListBox);
+
+ protected override IItemContainerGenerator CreateItemContainerGenerator()
+ {
+ return new ItemContainerGenerator<NavBarItem>(
+ this,
+ ListBoxItem.ContentProperty,
+ ListBoxItem.ContentTemplateProperty);
+ }
+ }
+}

ADD
WalletWasabi.Fluent/Controls/NavBarTreeItem.xaml
+<Styles xmlns="https://github.com/avaloniaui"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:converters="clr-namespace:Avalonia.Controls.Converters;assembly=Avalonia.Controls"
+ xmlns:c="clr-namespace:WalletWasabi.Fluent.Controls">
+
+ <Styles.Resources>
+ <Thickness x:Key="ListBoxItemPadding">12,9,12,12</Thickness>
+ <x:Double x:Key="TreeViewItemIndent">16</x:Double>
+ <x:Double x:Key="TreeViewItemExpandCollapseChevronSize">12</x:Double>
+ <Thickness x:Key="TreeViewItemExpandCollapseChevronMargin">12, 0, 12, 0</Thickness>
+ <StreamGeometry x:Key="TreeViewItemCollapsedChevronPathData">M 1,0 10,10 l -9,10 -1,-1 L 8,10 -0,1 Z</StreamGeometry>
+ <StreamGeometry x:Key="TreeViewItemExpandedChevronPathData">M0,1 L10,10 20,1 19,0 10,8 1,0 Z</StreamGeometry>
+ <converters:MarginMultiplierConverter Indent="{StaticResource TreeViewItemIndent}"
+ Left="True"
+ x:Key="TreeViewItemLeftMarginConverter" />
+ </Styles.Resources>
+
+ <Style Selector="c|NavBarTreeItem">
+ <Style.Resources />
+ <Setter Property="Padding" Value="{StaticResource ListBoxItemPadding}" />
+ <Setter Property="Background" Value="{DynamicResource TreeViewItemBackground}" />
+ <Setter Property="BorderBrush" Value="{DynamicResource TreeViewItemBorderBrush}" />
+ <Setter Property="BorderThickness" Value="0" />
+ <Setter Property="Foreground" Value="{DynamicResource TreeViewItemForeground}" />
+ <Setter Property="MinHeight" Value="{DynamicResource TreeViewItemMinHeight}" />
+ <Setter Property="VerticalAlignment" Value="Center" />
+ <Setter Property="Template">
+ <ControlTemplate>
+ <StackPanel>
+ <Border Name="PART_LayoutRoot"
+ Classes="TreeViewItemLayoutRoot"
+ Focusable="True"
+ Background="{TemplateBinding Background}"
+ BorderBrush="{TemplateBinding BorderBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}"
+ MinHeight="{TemplateBinding MinHeight}"
+ TemplatedControl.IsTemplateFocusTarget="True">
+ <Grid Name="PART_Header"
+ Margin="{TemplateBinding Level, Mode=OneWay, Converter={StaticResource TreeViewItemLeftMarginConverter}}">
+ <Border x:Name="Indicator" BorderThickness="2 0 0 0" />
+ <ContentPresenter Name="PART_HeaderPresenter"
+ Focusable="False"
+ Content="{TemplateBinding Header}"
+ HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
+ VerticalAlignment="{TemplateBinding VerticalAlignment}"
+ Margin="{TemplateBinding Padding}" />
+ </Grid>
+ </Border>
+ <ItemsPresenter Name="PART_ItemsPresenter"
+ IsVisible="{TemplateBinding IsExpanded}"
+ Items="{TemplateBinding Items}"
+ ItemsPanel="{TemplateBinding ItemsPanel}" />
+ </StackPanel>
+ </ControlTemplate>
+ </Setter>
+ </Style>
+
+ <!-- PointerOver state -->
+ <Style Selector="c|NavBarTreeItem /template/ Border#PART_LayoutRoot:pointerover">
+ <Setter Property="Background" Value="{DynamicResource SystemControlHighlightListLowBrush}" />
+ <Setter Property="BorderBrush" Value="{DynamicResource TreeViewItemBorderBrushPointerOver}" />
+ </Style>
+ <Style Selector="c|NavBarTreeItem /template/ Border#PART_LayoutRoot:pointerover > ContentPresenter#PART_HeaderPresenter">
+ <Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundPointerOver}" />
+ </Style>
+
+ <!-- Pressed state -->
+ <Style Selector="c|NavBarTreeItem:pressed /template/ Border#Indicator">
+ <Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColorLight1}"/>
+ </Style>
+ <Style Selector="c|NavBarTreeItem:pressed /template/ Border#PART_LayoutRoot:pointerover > ContentPresenter#PART_HeaderPresenter">
+ <Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundPressed}" />
+ </Style>
+ <Style Selector="c|NavBarTreeItem /template/ Border#PART_LayoutRoot">
+ <Setter Property="RenderTransform" Value="none" />
+ <Setter Property="Transitions">
+ <Transitions>
+ <TransformOperationsTransition Property="RenderTransform" Duration="0:0:.075" />
+ </Transitions>
+ </Setter>
+ </Style>
+ <Style Selector="c|NavBarTreeItem:pressed /template/ Border#PART_LayoutRoot">
+ <Setter Property="RenderTransform" Value="scale(0.98)" />
+ </Style>
+
+ <!-- Disabled state -->
+ <Style Selector="c|NavBarTreeItem:disabled /template/ Border#PART_LayoutRoot > ContentPresenter#PART_HeaderPresenter">
+ <Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundDisabled}" />
+ </Style>
+
+ <!-- Selected state -->
+ <Style Selector="c|NavBarTreeItem:selected /template/ Border#Indicator">
+ <Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColor}"/>
+ </Style>
+ <Style Selector="c|NavBarTreeItem:selected /template/ Border#PART_LayoutRoot > ContentPresenter#PART_HeaderPresenter">
+ <Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundSelected}" />
+ </Style>
+
+ <!-- Selected PointerOver state -->
+ <Style Selector="c|NavBarTreeItem:selected /template/ Border#PART_LayoutRoot:pointerover > ContentPresenter#PART_HeaderPresenter">
+ <Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundSelectedPointerOver}" />
+ </Style>
+
+ <!-- Selected Pressed state -->
+ <Style Selector="c|NavBarTreeItem:pressed:selected /template/ Border#PART_LayoutRoot:pointerover > ContentPresenter#PART_HeaderPresenter">
+ <Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundSelectedPressed}" />
+ </Style>
+
+ <!-- Disabled Selected state -->
+ <Style Selector="c|NavBarTreeItem:disabled:selected /template/ Border#PART_LayoutRoot > ContentPresenter#PART_HeaderPresenter">
+ <Setter Property="TextBlock.Foreground" Value="{DynamicResource TreeViewItemForegroundSelectedDisabled}" />
+ </Style>
+
+ <!-- ExpandCollapseChevron Group states -->
+ <Style Selector="ToggleButton.ExpandCollapseChevron /template/ Path#ChevronPath">
+ <Setter Property="Data" Value="{StaticResource TreeViewItemCollapsedChevronPathData}" />
+ </Style>
+ <Style Selector="ToggleButton.ExpandCollapseChevron:checked /template/ Path#ChevronPath">
+ <Setter Property="Data" Value="{StaticResource TreeViewItemExpandedChevronPathData}" />
+ </Style>
+ <Style Selector="c|NavBarTreeItem:empty /template/ ToggleButton#PART_ExpandCollapseChevron">
+ <Setter Property="IsVisible" Value="False" />
+ </Style>
+ <Style Selector="c|NavBarTreeItem:empty /template/ Panel#PART_ExpandCollapseChevronContainer">
+ <Setter Property="Width" Value="{StaticResource TreeViewItemExpandCollapseChevronSize}" />
+ </Style>
+
+</Styles>
\ No newline at end of file

MODIFY
WalletWasabi.Fluent/Views/NavBar.axaml
WalletWasabi.Fluent/Views/NavBar.axaml
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="WalletWasabi.Fluent.Views.NavBar" UseLayoutRounding="False">
<UserControl.Styles>
+ <Style Selector=":is(ListBox)">
+ <Setter Property="ItemTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <Panel>
+ <Panel Width="45" HorizontalAlignment="Left">
+ <PathIcon HorizontalAlignment="Left" Data="{StaticResource add_circle_regular}" />
+ </Panel>
+ <TextBlock Text="{Binding Title}" Margin="35 0 0 0" />
+ </Panel>
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
<Style Selector="PathIcon">
<Setter Property="Margin" Value="1 0 0 0" />
</Style>
<Setter Property="Background" Value="Transparent" />
<Setter Property="Padding" Value="0" />
</Style>
- <Style Selector="ListBoxItem">
- <Setter Property="Margin" Value="0" />
- <Setter Property="Padding" Value="0" />
- <Setter Property="HorizontalContentAlignment" Value="Stretch" />
- </Style>
- <Style Selector="ListBoxItem:pointerover /template/ Rectangle#PressedBackground, ListBoxItem:selected /template/ Rectangle#PressedBackground">
- <Setter Property="Fill" Value="Transparent"/>
- </Style>
- <Style Selector="TreeViewItem">
+ <Style Selector="c|NavBarTreeItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded}" />
- <Setter Property="BorderThickness" Value="0" />
- </Style>
- <Style Selector="TreeViewItem /template/ Border#PART_LayoutRoot:pointerover, TreeViewItem:selected /template/ Border#PART_LayoutRoot">
- <Setter Property="Background" Value="Transparent" />
- </Style>
- <Style Selector="c|NavBarItem TextBlock">
- <Setter Property="VerticalAlignment" Value="Center" />
- </Style>
- <Style Selector="TreeView > TreeViewItem /template/ Panel">
- <Setter Property="IsVisible" Value="False" />
- </Style>
- <Style Selector="TreeViewItem > TreeViewItem">
- <Setter Property="Margin" Value="-16 0 0 0" />
</Style>
<Style Selector=":is(Button).NavButton">
<Setter Property="Width" Value="{StaticResource SplitViewCompactPaneLength}" />
<Setter Property="Background" Value="{DynamicResource SystemControlHighlightListLowBrush}" />
</Style>
<Style Selector="c|NavBarItem">
- <Setter Property="IsSelected" Value="{Binding IsSelected}" />
<Setter Property="Header" Value="{Binding Title}" />
</Style>
</UserControl.Styles>
- <UserControl.DataTemplates>
- <DataTemplate DataType="vm:HomePageViewModel">
- <c:NavBarItem>
- <c:NavBarItem.Icon>
- <PathIcon Data="{StaticResource home_regular}" />
- </c:NavBarItem.Icon>
- </c:NavBarItem>
- </DataTemplate>
- <DataTemplate DataType="vm:SettingsPageViewModel">
- <c:NavBarItem>
- <c:NavBarItem.Icon>
- <PathIcon Data="{StaticResource settings_regular}" />
- </c:NavBarItem.Icon>
- </c:NavBarItem>
- </DataTemplate>
- <DataTemplate DataType="vm:AddWalletPageViewModel">
- <c:NavBarItem>
- <c:NavBarItem.Icon>
- <PathIcon Data="{StaticResource add_circle_regular}" />
- </c:NavBarItem.Icon>
- </c:NavBarItem>
- </DataTemplate>
- <TreeDataTemplate DataType="vm:ClosedWalletViewModel" ItemsSource="{Binding Items}">
- <c:NavBarItem>
- <c:NavBarItem.Icon>
- <PathIcon Data="{StaticResource web_asset_regular}" />
- </c:NavBarItem.Icon>
- </c:NavBarItem>
- </TreeDataTemplate>
- </UserControl.DataTemplates>
<DockPanel>
<StackPanel DockPanel.Dock="Top">
<StackPanel.Resources>
<Button Classes="NavButton" Command="{Binding DoToggleAction}">
<PathIcon Data="{StaticResource navigation_regular}" Width="16" />
</Button>
- <ListBox Items="{Binding TopItems}" SelectedItem="{Binding SelectedItem}" />
+ <c:NavBarListBox Items="{Binding TopItems}" SelectedItem="{Binding SelectedItem}" />
<Separator />
</StackPanel>
<StackPanel DockPanel.Dock="Bottom">
<Separator />
- <ListBox Items="{Binding BottomItems}" SelectedItem="{Binding SelectedItem}" />
+ <c:NavBarListBox Items="{Binding BottomItems}" SelectedItem="{Binding SelectedItem}" />
</StackPanel>
- <TreeView Items="{Binding Items}" SelectedItem="{Binding SelectedItem}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" />
+ <c:NavBarTreeView Items="{Binding Items}" SelectedItem="{Binding SelectedItem}" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
+ <c:NavBarTreeView.ItemTemplate>
+ <TreeDataTemplate ItemsSource="{Binding Items}">
+ <Panel>
+ <Panel Width="45" HorizontalAlignment="Left">
+ <PathIcon HorizontalAlignment="Left" Data="{StaticResource add_circle_regular}" />
+ </Panel>
+ <TextBlock Text="{Binding Title}" Margin="35 0 0 0" />
+ </Panel>
+ </TreeDataTemplate>
+ </c:NavBarTreeView.ItemTemplate>
+ </c:NavBarTreeView>
</DockPanel>
</UserControl>

Use Generated NavBarItems.