diff --git a/samples/ControlCatalog/Pages/TreeViewPage.xaml b/samples/ControlCatalog/Pages/TreeViewPage.xaml
index c9e3fafb6d..6019d5f91f 100644
--- a/samples/ControlCatalog/Pages/TreeViewPage.xaml
+++ b/samples/ControlCatalog/Pages/TreeViewPage.xaml
@@ -19,7 +19,6 @@
-
diff --git a/samples/ControlCatalog/Pages/TreeViewPage.xaml.cs b/samples/ControlCatalog/Pages/TreeViewPage.xaml.cs
index 5893796b8b..3fb990459f 100644
--- a/samples/ControlCatalog/Pages/TreeViewPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/TreeViewPage.xaml.cs
@@ -1,9 +1,6 @@
-using System.Collections.ObjectModel;
-using System.Linq;
-using System.Reactive;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
-using ReactiveUI;
+using ControlCatalog.ViewModels;
namespace ControlCatalog.Pages
{
@@ -12,105 +9,12 @@ namespace ControlCatalog.Pages
public TreeViewPage()
{
InitializeComponent();
- DataContext = new PageViewModel();
+ DataContext = new TreeViewPageViewModel();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
-
- private class PageViewModel : ReactiveObject
- {
- private SelectionMode _selectionMode;
-
- public PageViewModel()
- {
- Node root = new Node();
- Items = root.Children;
- Selection = new SelectionModel();
-
- AddItemCommand = ReactiveCommand.Create(() =>
- {
- Node parentItem = Selection.SelectedItems.Count > 0 ?
- (Node)Selection.SelectedItems[0] : root;
- parentItem.AddNewItem();
- });
-
- RemoveItemCommand = ReactiveCommand.Create(() =>
- {
- while (Selection.SelectedItems.Count > 0)
- {
- Node lastItem = (Node)Selection.SelectedItems[0];
- RecursiveRemove(Items, lastItem);
- Selection.DeselectAt(Selection.SelectedIndices[0]);
- }
-
- bool RecursiveRemove(ObservableCollection items, Node selectedItem)
- {
- if (items.Remove(selectedItem))
- {
- return true;
- }
-
- foreach (Node item in items)
- {
- if (item.AreChildrenInitialized && RecursiveRemove(item.Children, selectedItem))
- {
- return true;
- }
- }
-
- return false;
- }
- });
- }
-
- public ObservableCollection Items { get; }
-
- public SelectionModel Selection { get; }
-
- public ReactiveCommand AddItemCommand { get; }
-
- public ReactiveCommand RemoveItemCommand { get; }
-
- public SelectionMode SelectionMode
- {
- get => _selectionMode;
- set
- {
- Selection.ClearSelection();
- this.RaiseAndSetIfChanged(ref _selectionMode, value);
- }
- }
- }
-
- private class Node
- {
- private int _counter;
- private ObservableCollection _children;
-
- public string Header { get; private set; }
-
- public bool AreChildrenInitialized => _children != null;
-
- public ObservableCollection Children
- {
- get
- {
- if (_children == null)
- {
- _children = new ObservableCollection(Enumerable.Range(1, 10).Select(i => CreateNewNode()));
- }
- return _children;
- }
- }
-
- public void AddNewItem() => Children.Add(CreateNewNode());
-
- public override string ToString() => Header;
-
- private Node CreateNewNode() => new Node { Header = $"Item {_counter++}" };
- }
}
}
diff --git a/samples/ControlCatalog/ViewModels/TreeViewPageViewModel.cs b/samples/ControlCatalog/ViewModels/TreeViewPageViewModel.cs
new file mode 100644
index 0000000000..d396ef2b3d
--- /dev/null
+++ b/samples/ControlCatalog/ViewModels/TreeViewPageViewModel.cs
@@ -0,0 +1,115 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reactive;
+using Avalonia.Controls;
+using ReactiveUI;
+
+namespace ControlCatalog.ViewModels
+{
+ public class TreeViewPageViewModel : ReactiveObject
+ {
+ private readonly Node _root;
+ private SelectionMode _selectionMode;
+
+ public TreeViewPageViewModel()
+ {
+ _root = new Node();
+
+ Items = _root.Children;
+ Selection = new SelectionModel();
+ Selection.SelectionChanged += SelectionChanged;
+
+ AddItemCommand = ReactiveCommand.Create(AddItem);
+ RemoveItemCommand = ReactiveCommand.Create(RemoveItem);
+ }
+
+ public ObservableCollection Items { get; }
+ public SelectionModel Selection { get; }
+ public ReactiveCommand AddItemCommand { get; }
+ public ReactiveCommand RemoveItemCommand { get; }
+
+ public SelectionMode SelectionMode
+ {
+ get => _selectionMode;
+ set
+ {
+ Selection.ClearSelection();
+ this.RaiseAndSetIfChanged(ref _selectionMode, value);
+ }
+ }
+
+ private void AddItem()
+ {
+ var parentItem = Selection.SelectedItems.Count > 0 ? (Node)Selection.SelectedItems[0] : _root;
+ parentItem.AddItem();
+ }
+
+ private void RemoveItem()
+ {
+ while (Selection.SelectedItems.Count > 0)
+ {
+ Node lastItem = (Node)Selection.SelectedItems[0];
+ RecursiveRemove(Items, lastItem);
+ Selection.DeselectAt(Selection.SelectedIndices[0]);
+ }
+
+ bool RecursiveRemove(ObservableCollection items, Node selectedItem)
+ {
+ if (items.Remove(selectedItem))
+ {
+ return true;
+ }
+
+ foreach (Node item in items)
+ {
+ if (item.AreChildrenInitialized && RecursiveRemove(item.Children, selectedItem))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+
+ private void SelectionChanged(object sender, SelectionModelSelectionChangedEventArgs e)
+ {
+ var selected = string.Join(",", e.SelectedIndices);
+ var deselected = string.Join(",", e.DeselectedIndices);
+ System.Diagnostics.Debug.WriteLine($"Selected '{selected}', Deselected '{deselected}'");
+ }
+
+ public class Node
+ {
+ private ObservableCollection _children;
+ private int _childIndex = 10;
+
+ public Node()
+ {
+ Header = "Item";
+ }
+
+ public Node(Node parent, int index)
+ {
+ Parent = parent;
+ Header = parent.Header + ' ' + index;
+ }
+
+ public Node Parent { get; }
+ public string Header { get; }
+ public bool AreChildrenInitialized => _children != null;
+ public ObservableCollection Children => _children ??= CreateChildren();
+ public void AddItem() => Children.Add(new Node(this, _childIndex++));
+ public void RemoveItem(Node child) => Children.Remove(child);
+ public override string ToString() => Header;
+
+ private ObservableCollection CreateChildren()
+ {
+ return new ObservableCollection(
+ Enumerable.Range(0, 10).Select(i => new Node(this, i)));
+ }
+ }
+ }
+}