mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-29 16:36:40 +01:00
Compare commits
11 Commits
leilzh/fui
...
dev/seraph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d28d8e501 | ||
|
|
32492772b8 | ||
|
|
6896f59d48 | ||
|
|
7ce347149f | ||
|
|
626d43f631 | ||
|
|
83aff2687d | ||
|
|
f8837c4ed0 | ||
|
|
9589d3bd74 | ||
|
|
f3b10bfa8e | ||
|
|
3e7c7d77df | ||
|
|
0badb19936 |
@@ -16,21 +16,31 @@ public partial class SamplesListPage : ListPage
|
||||
{
|
||||
Title = "List Page Sample Command",
|
||||
Subtitle = "Display a list of items",
|
||||
Section = "Lists",
|
||||
},
|
||||
new ListItem(new SampleListPageWithDetails())
|
||||
{
|
||||
Title = "List Page With Details",
|
||||
Subtitle = "A list of items, each with additional details to display",
|
||||
Section = "Lists",
|
||||
},
|
||||
new ListItem(new SampleUpdatingItemsPage())
|
||||
{
|
||||
Title = "List page with items that change",
|
||||
Subtitle = "The items on the list update themselves in real time",
|
||||
Section = "Lists",
|
||||
},
|
||||
new ListItem(new SampleDynamicListPage())
|
||||
{
|
||||
Title = "Dynamic List Page Command",
|
||||
Subtitle = "Changes the list of items in response to the typed query",
|
||||
Section = "Lists",
|
||||
},
|
||||
new ListItem(new FizzBuzzListPage())
|
||||
{
|
||||
Title = "Sections sample",
|
||||
Subtitle = "Changing list of items, with sections",
|
||||
Section = "Lists",
|
||||
},
|
||||
|
||||
// Content pages
|
||||
@@ -38,32 +48,38 @@ public partial class SamplesListPage : ListPage
|
||||
{
|
||||
Title = "Sample content page",
|
||||
Subtitle = "Display mixed forms, markdown, and other types of content",
|
||||
Section = "Content",
|
||||
},
|
||||
new ListItem(new SampleTreeContentPage())
|
||||
{
|
||||
Title = "Sample nested content",
|
||||
Subtitle = "Example of nesting a tree of content",
|
||||
Section = "Content",
|
||||
},
|
||||
new ListItem(new SampleCommentsPage())
|
||||
{
|
||||
Title = "Sample of nested comments",
|
||||
Subtitle = "Demo of using nested trees of content to create a comment thread-like experience",
|
||||
Icon = new IconInfo("\uE90A"), // Comment
|
||||
Section = "Content",
|
||||
},
|
||||
new ListItem(new SampleMarkdownPage())
|
||||
{
|
||||
Title = "Markdown Page Sample Command",
|
||||
Subtitle = "Display a page of rendered markdown",
|
||||
Section = "Content",
|
||||
},
|
||||
new ListItem(new SampleMarkdownManyBodies())
|
||||
{
|
||||
Title = "Markdown with multiple blocks",
|
||||
Subtitle = "A page with multiple blocks of rendered markdown",
|
||||
Section = "Content",
|
||||
},
|
||||
new ListItem(new SampleMarkdownDetails())
|
||||
{
|
||||
Title = "Markdown with details",
|
||||
Subtitle = "A page with markdown and details",
|
||||
Section = "Content",
|
||||
},
|
||||
|
||||
// Settings helpers
|
||||
@@ -71,6 +87,7 @@ public partial class SamplesListPage : ListPage
|
||||
{
|
||||
Title = "Sample settings page",
|
||||
Subtitle = "A demo of the settings helpers",
|
||||
Section = "Settings",
|
||||
},
|
||||
|
||||
// Evil edge cases
|
||||
@@ -79,6 +96,7 @@ public partial class SamplesListPage : ListPage
|
||||
{
|
||||
Title = "Evil samples",
|
||||
Subtitle = "Samples designed to break the palette in many different evil ways",
|
||||
Section = "Debugging",
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
|
||||
public partial class ListGroup : ObservableObject
|
||||
{
|
||||
public string Key { get; set; } = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<ListItemViewModel> Items { get; set; } = [];
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
@@ -27,6 +27,12 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
||||
|
||||
private ObservableCollection<ListItemViewModel> Items { get; set; } = [];
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool HasGrouping { get; private set; } = false;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<ListGroup> Groups { get; set; } = [];
|
||||
|
||||
private readonly ExtensionObject<IListPage> _model;
|
||||
|
||||
private readonly Lock _listLock = new();
|
||||
@@ -248,6 +254,53 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateGroupsIfNeeded()
|
||||
{
|
||||
HasGrouping = FilteredItems.Any(i => !string.IsNullOrEmpty(i.Section));
|
||||
|
||||
if (HasGrouping)
|
||||
{
|
||||
lock (_listLock)
|
||||
{
|
||||
if (FilteredItems.Count == 0)
|
||||
{
|
||||
Groups.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// get current groups
|
||||
var groups = FilteredItems.GroupBy(item => item.Section).Select(group => group);
|
||||
|
||||
// Remove any groups that no longer exist
|
||||
foreach (var group in Groups)
|
||||
{
|
||||
if (!groups.Any(g => g.Key == group.Key))
|
||||
{
|
||||
Groups.Remove(group);
|
||||
}
|
||||
}
|
||||
|
||||
// Update lists for each existing group
|
||||
foreach (var group in groups)
|
||||
{
|
||||
var existingGroup = Groups.FirstOrDefault(groupItem => groupItem.Key == group.Key);
|
||||
if (existingGroup == null)
|
||||
{
|
||||
// Add a new group if it doesn't exist
|
||||
Groups.Add(new ListGroup { Key = group.Key, Items = new ObservableCollection<ListItemViewModel>(group) });
|
||||
existingGroup = Groups.FirstOrDefault(groupItem => groupItem.Key == group.Key);
|
||||
}
|
||||
|
||||
if (existingGroup != null)
|
||||
{
|
||||
// Update the existing group
|
||||
ListHelpers.InPlaceUpdateList(existingGroup.Items, FilteredItems.Where(item => item.Section == group.Key));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply our current filter text to the list of items, and update
|
||||
/// FilteredItems to match the results.
|
||||
@@ -487,6 +540,18 @@ public partial class ListViewModel : PageViewModel, IDisposable
|
||||
}
|
||||
|
||||
FilteredItems.Clear();
|
||||
|
||||
foreach (ListGroup group in Groups)
|
||||
{
|
||||
foreach (ListItemViewModel item in group.Items)
|
||||
{
|
||||
item.SafeCleanup();
|
||||
}
|
||||
|
||||
group.Items.Clear();
|
||||
}
|
||||
|
||||
Groups.Clear();
|
||||
}
|
||||
|
||||
IListPage? model = _model.Unsafe;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<!-- Other merged dictionaries here -->
|
||||
<ResourceDictionary Source="Styles/Button.xaml" />
|
||||
<ResourceDictionary Source="Styles/Colors.xaml" />
|
||||
<ResourceDictionary Source="Styles/Generic.xaml" />
|
||||
<ResourceDictionary Source="Styles/TextBox.xaml" />
|
||||
<ResourceDictionary Source="Styles/Settings.xaml" />
|
||||
<ResourceDictionary Source="Controls/Tag.xaml" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Page
|
||||
x:Class="Microsoft.CmdPal.UI.ListPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
@@ -17,10 +17,16 @@
|
||||
<Page.Resources>
|
||||
<!-- TODO: Figure out what we want to do here for filtering/grouping and where -->
|
||||
<!-- https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.collectionviewsource -->
|
||||
<!--<CollectionViewSource
|
||||
x:Name="ItemsCVS"
|
||||
<CollectionViewSource
|
||||
x:Name="GroupedItemsCVS"
|
||||
IsSourceGrouped="True"
|
||||
Source="{x:Bind ViewModel.Items, Mode=OneWay}" />-->
|
||||
ItemsPath="Items"
|
||||
Source="{x:Bind ViewModel.Groups, Mode=OneWay}" />
|
||||
|
||||
<CollectionViewSource
|
||||
x:Name="UngroupedItemsCVS"
|
||||
IsSourceGrouped="False"
|
||||
Source="{x:Bind ViewModel.FilteredItems, Mode=OneWay}" />
|
||||
|
||||
<converters:StringVisibilityConverter
|
||||
x:Key="StringVisibilityConverter"
|
||||
@@ -107,32 +113,74 @@
|
||||
TargetType="x:Boolean"
|
||||
Value="{x:Bind ViewModel.ShowEmptyContent, Mode=OneWay}">
|
||||
<controls:Case Value="False">
|
||||
<ListView
|
||||
x:Name="ItemsList"
|
||||
Padding="0,2,0,0"
|
||||
DoubleTapped="ItemsList_DoubleTapped"
|
||||
IsDoubleTapEnabled="True"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="ItemsList_ItemClick"
|
||||
ItemTemplate="{StaticResource ListItemViewModelTemplate}"
|
||||
ItemsSource="{x:Bind ViewModel.FilteredItems, Mode=OneWay}"
|
||||
SelectionChanged="ItemsList_SelectionChanged">
|
||||
<ListView.ItemContainerTransitions>
|
||||
<TransitionCollection />
|
||||
</ListView.ItemContainerTransitions>
|
||||
<!--<ListView.GroupStyle>
|
||||
<GroupStyle HidesIfEmpty="True">
|
||||
<GroupStyle.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock
|
||||
Margin="0,16,0,0"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding Key, Mode=OneWay}" />
|
||||
</DataTemplate>
|
||||
</GroupStyle.HeaderTemplate>
|
||||
</GroupStyle>
|
||||
</ListView.GroupStyle>-->
|
||||
</ListView>
|
||||
<controls:SwitchPresenter
|
||||
HorizontalAlignment="Stretch"
|
||||
TargetType="x:Boolean"
|
||||
Value="{x:Bind ViewModel.HasGrouping, Mode=OneWay}">
|
||||
<controls:Case Value="True">
|
||||
<ListView
|
||||
x:Name="GroupedItemsList"
|
||||
Padding="0,2,0,0"
|
||||
DoubleTapped="GroupedItemsList_DoubleTapped"
|
||||
IsDoubleTapEnabled="True"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="ItemsList_ItemClick"
|
||||
ItemTemplate="{StaticResource ListItemViewModelTemplate}"
|
||||
ItemsSource="{Binding ElementName=GroupedItemsCVS, Path=View}"
|
||||
SelectionChanged="GroupedItemsList_SelectionChanged">
|
||||
<ListView.ItemContainerTransitions>
|
||||
<TransitionCollection />
|
||||
</ListView.ItemContainerTransitions>
|
||||
<ListView.GroupStyle>
|
||||
<!--<GroupStyle HeaderContainerStyle="{StaticResource CustomHeaderContainerStyle}" HidesIfEmpty="True">
|
||||
<GroupStyle.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock
|
||||
Padding="20,12,0,8"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Text="{x:Bind Key}"
|
||||
Visibility="{x:Bind Key, Converter={StaticResource StringNotEmptyToVisibilityConverter}, Mode=OneWay}" />
|
||||
</DataTemplate>
|
||||
</GroupStyle.HeaderTemplate>
|
||||
</GroupStyle>-->
|
||||
|
||||
<GroupStyle HeaderContainerStyle="{StaticResource CustomHeaderContainerStyle}" HidesIfEmpty="True">
|
||||
<GroupStyle.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock
|
||||
Margin="0,16,0,0"
|
||||
Padding="20,8,0,4"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="{Binding Key, Mode=OneWay}"
|
||||
Visibility="{Binding Key, Converter={StaticResource StringVisibilityConverter}}" />
|
||||
</DataTemplate>
|
||||
</GroupStyle.HeaderTemplate>
|
||||
</GroupStyle>
|
||||
</ListView.GroupStyle>
|
||||
</ListView>
|
||||
</controls:Case>
|
||||
<controls:Case Value="False">
|
||||
<ListView
|
||||
x:Name="ItemsList"
|
||||
Padding="0,2,0,0"
|
||||
DoubleTapped="ItemsList_DoubleTapped"
|
||||
IsDoubleTapEnabled="True"
|
||||
IsItemClickEnabled="True"
|
||||
ItemClick="ItemsList_ItemClick"
|
||||
ItemTemplate="{StaticResource ListItemViewModelTemplate}"
|
||||
ItemsSource="{Binding ElementName=UngroupedItemsCVS, Path=View}"
|
||||
SelectionChanged="ItemsList_SelectionChanged">
|
||||
<ListView.ItemContainerTransitions>
|
||||
<TransitionCollection />
|
||||
</ListView.ItemContainerTransitions>
|
||||
</ListView>
|
||||
</controls:Case>
|
||||
</controls:SwitchPresenter>
|
||||
</controls:Case>
|
||||
<controls:Case Value="True">
|
||||
<StackPanel
|
||||
|
||||
@@ -37,6 +37,7 @@ public sealed partial class ListPage : Page,
|
||||
this.InitializeComponent();
|
||||
this.NavigationCacheMode = NavigationCacheMode.Disabled;
|
||||
this.ItemsList.Loaded += ItemsList_Loaded;
|
||||
this.GroupedItemsList.Loaded += GroupedItemsList_Loaded;
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
@@ -121,6 +122,18 @@ public sealed partial class ListPage : Page,
|
||||
}
|
||||
}
|
||||
|
||||
private void GroupedItemsList_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
|
||||
{
|
||||
if (GroupedItemsList.SelectedItem is ListItemViewModel vm)
|
||||
{
|
||||
var settings = App.Current.Services.GetService<SettingsModel>()!;
|
||||
if (!settings.SingleClickActivates)
|
||||
{
|
||||
ViewModel?.InvokeItemCommand.Execute(vm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "VS is too aggressive at pruning methods bound in XAML")]
|
||||
private void ItemsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
@@ -148,6 +161,24 @@ public sealed partial class ListPage : Page,
|
||||
}
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "VS is too aggressive at pruning methods bound in XAML")]
|
||||
private void GroupedItemsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (GroupedItemsList.SelectedItem is ListItemViewModel item)
|
||||
{
|
||||
var vm = ViewModel;
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
vm?.UpdateSelectedItemCommand.Execute(item);
|
||||
});
|
||||
}
|
||||
|
||||
if (GroupedItemsList.SelectedItem != null)
|
||||
{
|
||||
GroupedItemsList.ScrollIntoView(GroupedItemsList.SelectedItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void ItemsList_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Find the ScrollViewer in the ListView
|
||||
@@ -159,6 +190,17 @@ public sealed partial class ListPage : Page,
|
||||
}
|
||||
}
|
||||
|
||||
private void GroupedItemsList_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Find the ScrollViewer in the ListView
|
||||
var listViewScrollViewer = FindScrollViewer(this.GroupedItemsList);
|
||||
|
||||
if (listViewScrollViewer != null)
|
||||
{
|
||||
listViewScrollViewer.ViewChanged += ListViewScrollViewer_ViewChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void ListViewScrollViewer_ViewChanged(object? sender, ScrollViewerViewChangedEventArgs e)
|
||||
{
|
||||
var scrollView = sender as ScrollViewer;
|
||||
@@ -187,6 +229,11 @@ public sealed partial class ListPage : Page,
|
||||
{
|
||||
ItemsList.SelectedIndex++;
|
||||
}
|
||||
|
||||
if (GroupedItemsList.SelectedIndex < GroupedItemsList.Items.Count - 1)
|
||||
{
|
||||
GroupedItemsList.SelectedIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(NavigatePreviousCommand message)
|
||||
@@ -195,6 +242,11 @@ public sealed partial class ListPage : Page,
|
||||
{
|
||||
ItemsList.SelectedIndex--;
|
||||
}
|
||||
|
||||
if (GroupedItemsList.SelectedIndex > 0)
|
||||
{
|
||||
GroupedItemsList.SelectedIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(ActivateSelectedListItemMessage message)
|
||||
@@ -207,6 +259,10 @@ public sealed partial class ListPage : Page,
|
||||
{
|
||||
ViewModel?.InvokeItemCommand.Execute(item);
|
||||
}
|
||||
else if (GroupedItemsList.SelectedItem is ListItemViewModel groupedItem)
|
||||
{
|
||||
ViewModel?.InvokeItemCommand.Execute(groupedItem);
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(ActivateSecondaryCommandMessage message)
|
||||
@@ -219,6 +275,10 @@ public sealed partial class ListPage : Page,
|
||||
{
|
||||
ViewModel?.InvokeSecondaryCommandCommand.Execute(item);
|
||||
}
|
||||
else if (GroupedItemsList.SelectedItem is ListItemViewModel groupedItem)
|
||||
{
|
||||
ViewModel?.InvokeSecondaryCommandCommand.Execute(groupedItem);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnViewModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
@@ -247,6 +307,11 @@ public sealed partial class ListPage : Page,
|
||||
// GetItems or a change in the filter.
|
||||
private void Page_ItemsUpdated(ListViewModel sender, object args)
|
||||
{
|
||||
if (ViewModel != null)
|
||||
{
|
||||
ViewModel?.UpdateGroupsIfNeeded();
|
||||
}
|
||||
|
||||
// If for some reason, we don't have a selected item, fix that.
|
||||
//
|
||||
// It's important to do this here, because once there's no selection
|
||||
@@ -258,6 +323,11 @@ public sealed partial class ListPage : Page,
|
||||
{
|
||||
ItemsList.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
if (GroupedItemsList.SelectedItem == null)
|
||||
{
|
||||
GroupedItemsList.SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void ViewModel_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
|
||||
29
src/modules/cmdpal/Microsoft.CmdPal.UI/Styles/Generic.xaml
Normal file
29
src/modules/cmdpal/Microsoft.CmdPal.UI/Styles/Generic.xaml
Normal file
@@ -0,0 +1,29 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
|
||||
<!-- Using custom style to remove header divider from list view headers -->
|
||||
<Style x:Key="CustomHeaderContainerStyle" TargetType="ListViewHeaderItem">
|
||||
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontSize" Value="{ThemeResource ListViewHeaderItemThemeFontSize}" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Margin" Value="0,0,0,0" />
|
||||
<Setter Property="Padding" Value="12,8,12,0" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="MinHeight" Value="0" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="True" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ListViewHeaderItem">
|
||||
<ContentPresenter
|
||||
x:Name="ContentPresenter"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTransitions="{TemplateBinding ContentTransitions}" />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace SamplePagesExtension;
|
||||
|
||||
internal sealed partial class FizzBuzzListPage : ListPage
|
||||
{
|
||||
public override string Title => "FizzBuzz Page";
|
||||
|
||||
public override IconInfo Icon => new("\uE94C"); // % symbol
|
||||
|
||||
public override string Name => "Open";
|
||||
|
||||
private readonly List<ListItem> _items;
|
||||
|
||||
internal FizzBuzzListPage()
|
||||
{
|
||||
var addNewItem = new ListItem(new AnonymousCommand(() =>
|
||||
{
|
||||
var c = _items.Count;
|
||||
var f = c % 3 == 0;
|
||||
var b = c % 5 == 0;
|
||||
var s = string.Empty;
|
||||
if (f)
|
||||
{
|
||||
s += "Fizz";
|
||||
}
|
||||
|
||||
if (b)
|
||||
{
|
||||
s += "Buzz";
|
||||
}
|
||||
|
||||
_items.Add(new ListItem(new NoOpCommand())
|
||||
{
|
||||
Title = $"{c}",
|
||||
Icon = IconFromIndex(_items.Count),
|
||||
Section = s,
|
||||
});
|
||||
RaiseItemsChanged();
|
||||
})
|
||||
{ Result = CommandResult.KeepOpen() })
|
||||
{
|
||||
Title = "Add item",
|
||||
Subtitle = "Each item will be sorted into sections. Add at least three",
|
||||
Icon = new IconInfo("\uED0E"),
|
||||
};
|
||||
|
||||
_items = [addNewItem];
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems()
|
||||
{
|
||||
return _items.ToArray();
|
||||
}
|
||||
|
||||
private IconInfo IconFromIndex(int index)
|
||||
{
|
||||
return _icons[index % _icons.Length];
|
||||
}
|
||||
|
||||
private readonly IconInfo[] _icons =
|
||||
[
|
||||
new IconInfo("\ue700"),
|
||||
new IconInfo("\ue701"),
|
||||
new IconInfo("\ue702"),
|
||||
new IconInfo("\ue703"),
|
||||
new IconInfo("\ue704"),
|
||||
new IconInfo("\ue705"),
|
||||
new IconInfo("\ue706"),
|
||||
new IconInfo("\ue707"),
|
||||
new IconInfo("\ue708"),
|
||||
new IconInfo("\ue709"),
|
||||
new IconInfo("\ue70a"),
|
||||
new IconInfo("\ue70b"),
|
||||
new IconInfo("\ue70c"),
|
||||
new IconInfo("\ue70d"),
|
||||
new IconInfo("\ue70e"),
|
||||
new IconInfo("\ue70f"),
|
||||
new IconInfo("\ue710"),
|
||||
new IconInfo("\ue711"),
|
||||
new IconInfo("\ue712"),
|
||||
new IconInfo("\ue713"),
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user