Added groupings
MODIFY
WalletWasabi.Fluent/ViewModels/SearchBar/SearchBarDesignViewModel.cs
WalletWasabi.Fluent/ViewModels/SearchBar/SearchBarDesignViewModel.cs
using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reactive.Linq;
+using DynamicData;
using ReactiveUI;
namespace WalletWasabi.Fluent.ViewModels.SearchBar;
public class SearchBarDesignViewModel : ReactiveObject
{
- public ReadOnlyObservableCollection<SearchItem> Items { get; } = new(new ObservableCollection<SearchItem>(new[]
+ private readonly SearchItem[] _items;
+
+ public SearchBarDesignViewModel()
+ {
+ _items = new[]
+ {
+ new SearchItem("Test 1: Short", "Description short", null, "Settings") {Icon = "settings_bitcoin_regular"},
+ new SearchItem("Test 2: Loooooooooooong", "Description long", null, "Settings")
+ {Icon = "settings_bitcoin_regular"},
+ new SearchItem("Test 3: Short again", "Description very very loooooooooooong and difficult to read", null,
+ "Settings")
+ {Icon = "settings_bitcoin_regular"},
+ new SearchItem("Test 3", "Another", null, "Settings") {Icon = "settings_bitcoin_regular"},
+ new SearchItem("Test 4: Help topics", "Description very very loooooooooooong and difficult to read", null,
+ "Help")
+ {Icon = "settings_bitcoin_regular"},
+ new SearchItem("Test 3", "Another", null, "Help") {Icon = "settings_bitcoin_regular"}
+ };
+ }
+
+ public ReadOnlyObservableCollection<SearchItemGroup> Groups => new(new ObservableCollection<SearchItemGroup>(_items
+ .GroupBy(r => r.Category)
+ .Select(g =>
{
- new SearchItem("Test 1: Short", "Description short", null) {Icon = "settings_bitcoin_regular"},
- new SearchItem("Test 2: Loooooooooooong", "Description long", null) {Icon = "settings_bitcoin_regular"},
- new SearchItem("Test 3: Short again", "Description very very loooooooooooong and difficult to read", null)
- {Icon = "settings_bitcoin_regular"}, new SearchItem("Test 3", "Another", null) {Icon = "settings_bitcoin_regular"}
- }));
+ var sourceCache = new SourceCache<SearchItem, ComposedKey>(r => r.Key);
+ var observable = g.ToObservable();
+ sourceCache.PopulateFrom(observable);
+ return new SearchItemGroup(g.Key, sourceCache);
+ })));
public string SearchText => "Sample text";
}
\ No newline at end of file

MODIFY
WalletWasabi.Fluent/ViewModels/SearchBar/SearchItem.cs
WalletWasabi.Fluent/ViewModels/SearchBar/SearchItem.cs
using System.Windows.Input;
-namespace WalletWasabi.Fluent.ViewModels.SearchBar
-{
+namespace WalletWasabi.Fluent.ViewModels.SearchBar;
+
public class SearchItem
{
public ICommand Command { get; }
- public SearchItem(string name, string description, ICommand command)
+ public SearchItem(string name, string description, ICommand command, string category)
{
Name = name;
Description = description;
Command = command;
+ Category = category;
}
public string Name { get; }
public string Description { get; }
public ComposedKey Key => new(Name);
public string Icon { get; set; }
- }
+ public string Category { get; }
}
\ No newline at end of file

ADD
WalletWasabi.Fluent/ViewModels/SearchBar/SearchItemGroup.cs
+using System.Collections.ObjectModel;
+using System.Reactive.Linq;
+using DynamicData;
+using ReactiveUI;
+
+namespace WalletWasabi.Fluent.ViewModels.SearchBar;
+
+public class SearchItemGroup
+{
+ private readonly ReadOnlyObservableCollection<SearchItem> _items;
+
+ public SearchItemGroup(string title, IObservableCache<SearchItem, ComposedKey> groupCache)
+ {
+ Title = title;
+ groupCache.Connect()
+ .Bind(out _items)
+ .DisposeMany()
+ .ObserveOn(RxApp.MainThreadScheduler)
+ .Subscribe();
+ }
+
+ public string Title { get; }
+
+ public ReadOnlyObservableCollection<SearchItem> Items => _items;
+}
\ No newline at end of file

MODIFY
WalletWasabi.Fluent/Views/SearchBar/SearchBar.axaml
WalletWasabi.Fluent/Views/SearchBar/SearchBar.axaml
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="WalletWasabi.Fluent.Views.SearchBar.SearchBar"
- xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity"
- xmlns:ia="clr-namespace:Avalonia.Xaml.Interactions.Core;assembly=Avalonia.Xaml.Interactions"
xmlns:searchBar="clr-namespace:WalletWasabi.Fluent.ViewModels.SearchBar"
- xmlns:searchBar1="clr-namespace:WalletWasabi.Fluent.Views.SearchBar"
+ xmlns:s="clr-namespace:WalletWasabi.Fluent.Views.SearchBar"
x:Name="UserControl">
<Design.DataContext>
<searchBar:SearchBarDesignViewModel />
</Design.DataContext>
+ <UserControl.Styles>
+ <Style Selector="ItemsControl:empty">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <TextBlock>No results</TextBlock>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+ </UserControl.Styles>
+
<Panel>
- <TextBox Classes="" x:Name="Parent" DockPanel.Dock="Top" Text="{Binding SearchText, Mode=TwoWay}">
- <i:Interaction.Behaviors>
- <ia:EventTriggerBehavior EventName="GotFocus">
- <ia:ChangePropertyAction TargetObject="{Binding #Popup}" PropertyName="IsOpen" Value="True" />
- </ia:EventTriggerBehavior>
- <!--<ia:EventTriggerBehavior EventName="LostFocus">
- <ia:ChangePropertyAction TargetObject="{Binding #Popup}" PropertyName="IsOpen" Value="False" />
- </ia:EventTriggerBehavior>-->
- </i:Interaction.Behaviors>
- </TextBox>
- <Popup x:Name="Popup" PlacementTarget="{Binding #Parent}">
- <searchBar1:SearchBarDropdown MaxHeight="500" />
+ <TextBox x:Name="SearchBox" DockPanel.Dock="Top" Text="{Binding SearchText, Mode=TwoWay}" />
+ <Popup x:Name="Popup" IsLightDismissEnabled="True" IsOpen="{Binding #UserControl.IsKeyboardFocusWithin}"
+ PlacementTarget="{Binding #SearchBox}">
+ <s:SearchBarDropdown MaxHeight="500" />
</Popup>
</Panel>
</UserControl>
\ No newline at end of file

MODIFY
WalletWasabi.Fluent/Views/SearchBar/SearchBar.axaml.cs
WalletWasabi.Fluent/Views/SearchBar/SearchBar.axaml.cs
@@ -28,7 +28,7 @@ public class SearchBar : UserControl
.Select(m =>
{
var reactiveCommand = ReactiveCommand.Create(() => MainViewModel.Instance.MainScreen.To(new AboutViewModel()));
- var searchItem = new SearchItem(m.Title, m.Caption, reactiveCommand){ Icon = m.IconName };
+ var searchItem = new SearchItem(m.Title, m.Caption, reactiveCommand, m.Category ?? "No category"){ Icon = m.IconName };
return searchItem;
});

MODIFY
WalletWasabi.Fluent/Views/SearchBar/SearchBarDropdown.axaml
WalletWasabi.Fluent/Views/SearchBar/SearchBarDropdown.axaml
x:Class="WalletWasabi.Fluent.Views.SearchBar.SearchBarDropdown"
xmlns:searchBar="clr-namespace:WalletWasabi.Fluent.ViewModels.SearchBar"
xmlns:ia="clr-namespace:Avalonia.Xaml.Interactions.Core;assembly=Avalonia.Xaml.Interactions"
- xmlns:conv="clr-namespace:WalletWasabi.Fluent.Converters">
+ x:CompileBindings="True"
+ x:DataType="searchBar:SearchBarViewModel"
+ xmlns:conv="clr-namespace:WalletWasabi.Fluent.Converters" Background="{StaticResource SystemBaseLowColor}">
<Design.DataContext>
<searchBar:SearchBarDesignViewModel />
</Design.DataContext>
+ <ScrollViewer>
+ <ItemsControl Items="{Binding Groups}">
+ <ItemsControl.ItemTemplate>
+ <DataTemplate DataType="{x:Type searchBar:SearchItemGroup}">
+ <DockPanel>
+ <TextBlock Text="{Binding Title}" DockPanel.Dock="Top" />
<ListBox Items="{Binding Items}">
- <ListBox.Styles>
- <Style Selector="ListBox:empty">
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate>
- <TextBlock>No results</TextBlock>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
- </ListBox.Styles>
-
<ListBox.ItemTemplate>
<DataTemplate x:DataType="searchBar:SearchItem">
<DockPanel Background="Transparent">
<TextBlock FontWeight="ExtraLight" VerticalAlignment="Center" Text="{Binding Description}" />
</DockPanel.Children>
- <i:Interaction.Behaviors>
- <ia:EventTriggerBehavior EventName="PointerPressed">
- <ia:InvokeCommandAction Command="{Binding Command}" />
- <!--<ia:ChangePropertyAction TargetObject="{Binding #Popup}" PropertyName="IsOpen" Value="False"></ia:ChangePropertyAction>-->
- </ia:EventTriggerBehavior>
- </i:Interaction.Behaviors>
-
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</i:Interaction.Behaviors>
</ListBox>
+ </DockPanel>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ </ScrollViewer>
+
</UserControl>
\ No newline at end of file

Added groupings