7 changed files with 229 additions and 5 deletions
@ -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); |
|||
} |
|||
} |
|||
@ -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<PlaygroundItemViewModel> 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<PlaygroundItemViewModel> 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; |
|||
} |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
|||
xmlns:vm="using:VirtualizationDemo.ViewModels" |
|||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
|||
x:Class="VirtualizationDemo.Views.PlaygroundPageView" |
|||
x:DataType="vm:PlaygroundPageViewModel"> |
|||
<DockPanel> |
|||
<StackPanel DockPanel.Dock="Right" Margin="8 0" Width="200"> |
|||
<DropDownButton Content="Selection" HorizontalAlignment="Stretch"> |
|||
<Button.Flyout> |
|||
<Flyout> |
|||
<StackPanel> |
|||
<CheckBox IsChecked="{Binding Multiple}">Multiple</CheckBox> |
|||
<CheckBox IsChecked="{Binding Toggle}">Toggle</CheckBox> |
|||
<CheckBox IsChecked="{Binding AlwaysSelected}">AlwaysSelected</CheckBox> |
|||
<CheckBox IsChecked="{Binding #list.AutoScrollToSelectedItem}">AutoScrollToSelectedItem</CheckBox> |
|||
<CheckBox IsChecked="{Binding #list.WrapSelection}">WrapSelection</CheckBox> |
|||
</StackPanel> |
|||
</Flyout> |
|||
</Button.Flyout> |
|||
</DropDownButton> |
|||
|
|||
<Label>_Select Item</Label> |
|||
<DockPanel> |
|||
<TextBox x:Name="scrollToIndex" Text="{Binding ScrollToIndex}"> |
|||
<TextBox.InnerRightContent> |
|||
<StackPanel Orientation="Horizontal"> |
|||
<Button DockPanel.Dock="Right" |
|||
Command="{Binding RandomizeScrollToIndex}" |
|||
ToolTip.Tip="Randomize"> |
|||
⟳ |
|||
</Button> |
|||
<Button DockPanel.Dock="Right" |
|||
Command="{Binding ExecuteScrollToIndex}" |
|||
ToolTip.Tip="Execute"> |
|||
⮐ |
|||
</Button> |
|||
</StackPanel> |
|||
</TextBox.InnerRightContent> |
|||
</TextBox> |
|||
</DockPanel> |
|||
|
|||
<Label>New Item</Label> |
|||
<TextBox Text="{Binding NewItemHeader}"> |
|||
<TextBox.InnerRightContent> |
|||
<Button Command="{Binding AddAtSelectedIndex}" |
|||
ToolTip.Tip="Add at Selected Index">+</Button> |
|||
</TextBox.InnerRightContent> |
|||
</TextBox> |
|||
|
|||
<Button Command="{Binding DeleteSelectedItem}" Margin="0 8 0 0"> |
|||
Delete Selected |
|||
</Button> |
|||
</StackPanel> |
|||
|
|||
<TextBlock Name="itemCount" DockPanel.Dock="Bottom"/> |
|||
|
|||
<ListBox Name="list" |
|||
ItemsSource="{Binding Items}" |
|||
DisplayMemberBinding="{Binding Header}" |
|||
Selection="{Binding Selection}" |
|||
SelectionMode="{Binding SelectionMode}"/> |
|||
</DockPanel> |
|||
</UserControl> |
|||
@ -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; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue