From 36444706c138bf99388534ca908c6ca805bd4fa2 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 3 Apr 2023 15:22:08 +0200 Subject: [PATCH] Added a playground page to virtualization demo. For testing selection, collection changes and scroll into view etc. --- samples/VirtualizationDemo/MainWindow.axaml | 9 +- samples/VirtualizationDemo/Models/Chat.cs | 2 +- .../ViewModels/MainWindowViewModel.cs | 1 + .../ViewModels/PlaygroundItemViewModel.cs | 17 ++++ .../ViewModels/PlaygroundPageViewModel.cs | 95 +++++++++++++++++++ .../Views/PlaygroundPageView.axaml | 66 +++++++++++++ .../Views/PlaygroundPageView.axaml.cs | 44 +++++++++ 7 files changed, 229 insertions(+), 5 deletions(-) create mode 100644 samples/VirtualizationDemo/ViewModels/PlaygroundItemViewModel.cs create mode 100644 samples/VirtualizationDemo/ViewModels/PlaygroundPageViewModel.cs create mode 100644 samples/VirtualizationDemo/Views/PlaygroundPageView.axaml create mode 100644 samples/VirtualizationDemo/Views/PlaygroundPageView.axaml.cs diff --git a/samples/VirtualizationDemo/MainWindow.axaml b/samples/VirtualizationDemo/MainWindow.axaml index e064e6ab32..04e75450bf 100644 --- a/samples/VirtualizationDemo/MainWindow.axaml +++ b/samples/VirtualizationDemo/MainWindow.axaml @@ -5,14 +5,15 @@ xmlns:views="using:VirtualizationDemo.Views" x:Class="VirtualizationDemo.MainWindow" Title="AvaloniaUI Virtualization Demo" - Width="800" - Height="600" x:DataType="vm:MainWindowViewModel"> - + + + + - + diff --git a/samples/VirtualizationDemo/Models/Chat.cs b/samples/VirtualizationDemo/Models/Chat.cs index e84760135c..8a701cc454 100644 --- a/samples/VirtualizationDemo/Models/Chat.cs +++ b/samples/VirtualizationDemo/Models/Chat.cs @@ -16,7 +16,7 @@ public class ChatFile }; using var s = File.OpenRead(path); - return JsonSerializer.Deserialize(s, options); + return JsonSerializer.Deserialize(s, options)!; } } diff --git a/samples/VirtualizationDemo/ViewModels/MainWindowViewModel.cs b/samples/VirtualizationDemo/ViewModels/MainWindowViewModel.cs index 6432503595..478e40187e 100644 --- a/samples/VirtualizationDemo/ViewModels/MainWindowViewModel.cs +++ b/samples/VirtualizationDemo/ViewModels/MainWindowViewModel.cs @@ -4,6 +4,7 @@ namespace VirtualizationDemo.ViewModels; internal class MainWindowViewModel : ViewModelBase { + public PlaygroundPageViewModel Playground { get; } = new(); public ChatPageViewModel Chat { get; } = new(); public ExpanderPageViewModel Expanders { get; } = new(); } diff --git a/samples/VirtualizationDemo/ViewModels/PlaygroundItemViewModel.cs b/samples/VirtualizationDemo/ViewModels/PlaygroundItemViewModel.cs new file mode 100644 index 0000000000..584ef4600b --- /dev/null +++ b/samples/VirtualizationDemo/ViewModels/PlaygroundItemViewModel.cs @@ -0,0 +1,17 @@ +using MiniMvvm; + +namespace VirtualizationDemo.ViewModels; + +public class PlaygroundItemViewModel : ViewModelBase +{ + private string? _header; + + public PlaygroundItemViewModel(int index) => Header = $"Item {index}"; + public PlaygroundItemViewModel(string? header) => Header = header; + + public string? Header + { + get => _header; + set => RaiseAndSetIfChanged(ref _header, value); + } +} diff --git a/samples/VirtualizationDemo/ViewModels/PlaygroundPageViewModel.cs b/samples/VirtualizationDemo/ViewModels/PlaygroundPageViewModel.cs new file mode 100644 index 0000000000..98ab91b0a6 --- /dev/null +++ b/samples/VirtualizationDemo/ViewModels/PlaygroundPageViewModel.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.ObjectModel; +using System.Linq; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Selection; +using MiniMvvm; + +namespace VirtualizationDemo.ViewModels; + +public class PlaygroundPageViewModel : ViewModelBase +{ + private SelectionMode _selectionMode = SelectionMode.Multiple; + private int _scrollToIndex = 500; + private string? _newItemHeader = "New Item 1"; + + public PlaygroundPageViewModel() + { + Items = new(Enumerable.Range(0, 1000).Select(x => new PlaygroundItemViewModel(x))); + Selection = new(); + } + + public ObservableCollection Items { get; } + + public bool Multiple + { + get => _selectionMode.HasAnyFlag(SelectionMode.Multiple); + set => SetSelectionMode(SelectionMode.Multiple, value); + } + + public bool Toggle + { + get => _selectionMode.HasAnyFlag(SelectionMode.Toggle); + set => SetSelectionMode(SelectionMode.Toggle, value); + } + + public bool AlwaysSelected + { + get => _selectionMode.HasAnyFlag(SelectionMode.AlwaysSelected); + set => SetSelectionMode(SelectionMode.AlwaysSelected, value); + } + + public SelectionModel Selection { get; } + + public SelectionMode SelectionMode + { + get => _selectionMode; + set => RaiseAndSetIfChanged(ref _selectionMode, value); + } + + public int ScrollToIndex + { + get => _scrollToIndex; + set => RaiseAndSetIfChanged(ref _scrollToIndex, value); + } + + public string? NewItemHeader + { + get => _newItemHeader; + set => RaiseAndSetIfChanged(ref _newItemHeader, value); + } + + public void ExecuteScrollToIndex() + { + Selection.Select(ScrollToIndex); + } + + public void RandomizeScrollToIndex() + { + var rnd = new Random(); + ScrollToIndex = rnd.Next(Items.Count); + } + + public void AddAtSelectedIndex() + { + if (Selection.SelectedIndex == -1) + return; + Items.Insert(Selection.SelectedIndex, new(NewItemHeader)); + } + + public void DeleteSelectedItem() + { + var count = Selection.Count; + for (var i = count - 1; i >= 0; i--) + Items.RemoveAt(Selection.SelectedIndexes[i]); + } + + private void SetSelectionMode(SelectionMode mode, bool value) + { + if (value) + SelectionMode |= mode; + else + SelectionMode &= ~mode; + } +} diff --git a/samples/VirtualizationDemo/Views/PlaygroundPageView.axaml b/samples/VirtualizationDemo/Views/PlaygroundPageView.axaml new file mode 100644 index 0000000000..52bc6fd27a --- /dev/null +++ b/samples/VirtualizationDemo/Views/PlaygroundPageView.axaml @@ -0,0 +1,66 @@ + + + + + + + + Multiple + Toggle + AlwaysSelected + AutoScrollToSelectedItem + WrapSelection + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/VirtualizationDemo/Views/PlaygroundPageView.axaml.cs b/samples/VirtualizationDemo/Views/PlaygroundPageView.axaml.cs new file mode 100644 index 0000000000..5282475778 --- /dev/null +++ b/samples/VirtualizationDemo/Views/PlaygroundPageView.axaml.cs @@ -0,0 +1,44 @@ +using System; +using System.Linq; +using System.Threading; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using Avalonia.Threading; + +namespace VirtualizationDemo.Views; + +public partial class PlaygroundPageView : UserControl +{ + private DispatcherTimer _timer; + + public PlaygroundPageView() + { + InitializeComponent(); + + _timer = new DispatcherTimer + { + Interval = TimeSpan.FromMilliseconds(500), + }; + + _timer.Tick += TimerTick; + } + + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnAttachedToVisualTree(e); + _timer.Start(); + } + + protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnDetachedFromVisualTree(e); + _timer.Stop(); + } + + private void TimerTick(object? sender, EventArgs e) + { + var message = $"Realized {list.GetRealizedContainers().Count()} of {list.ItemsPanelRoot?.Children.Count}"; + itemCount.Text = message; + } +}