From 1707496b3f6adb5fa1c28f7edc89315b4ec3fdb7 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Sat, 29 Jun 2019 16:49:05 +0300 Subject: [PATCH 1/5] Add `Add`, `Remove` buttons and `SelectionMode` combobox to ListBoxPage.xaml --- samples/ControlCatalog/Pages/ListBoxPage.xaml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/samples/ControlCatalog/Pages/ListBoxPage.xaml b/samples/ControlCatalog/Pages/ListBoxPage.xaml index 4783c8cfb8..e7c81a28d4 100644 --- a/samples/ControlCatalog/Pages/ListBoxPage.xaml +++ b/samples/ControlCatalog/Pages/ListBoxPage.xaml @@ -9,7 +9,20 @@ Margin="0,16,0,0" HorizontalAlignment="Center" Spacing="16"> - + + + + + + + + + Single + Multiple + Toggle + AlwaysSelected + + From c3f0841142cd253c6b97ae31f9fbf965b472b9e7 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Sat, 29 Jun 2019 16:50:14 +0300 Subject: [PATCH 2/5] Implement functionality for added controls in ListBoxPage.xaml.cs --- .../ControlCatalog/Pages/ListBoxPage.xaml.cs | 52 ++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs b/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs index dbe6c74800..e1a615af4b 100644 --- a/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs +++ b/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs @@ -1,9 +1,9 @@ -using System; -using System.Collections; -using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; +using System.Reactive; using Avalonia.Controls; using Avalonia.Markup.Xaml; +using ReactiveUI; namespace ControlCatalog.Pages { @@ -11,9 +11,8 @@ namespace ControlCatalog.Pages { public ListBoxPage() { - this.InitializeComponent(); - DataContext = Enumerable.Range(1, 10).Select(i => $"Item {i}" ) - .ToArray(); + InitializeComponent(); + DataContext = new PageViewModel(this.Find("listBox")); } private void InitializeComponent() @@ -21,5 +20,46 @@ namespace ControlCatalog.Pages AvaloniaXamlLoader.Load(this); } + private class PageViewModel : ReactiveObject + { + private readonly ListBox _listBox; + private int _counter; + private SelectionMode _selectionMode; + + public PageViewModel(ListBox listBox) + { + _listBox = listBox; + + Items = new ObservableCollection(Enumerable.Range(1, 10).Select(i => GenerateItem())); + + AddItemCommand = ReactiveCommand.Create(() => Items.Add(GenerateItem())); + + RemoveItemCommand = ReactiveCommand.Create(() => + { + foreach (string selectedItem in listBox.SelectedItems) + { + Items.Remove(selectedItem); + } + }); + } + + public ObservableCollection Items { get; } + + public ReactiveCommand AddItemCommand { get; } + + public ReactiveCommand RemoveItemCommand { get; } + + public SelectionMode SelectionMode + { + get => _selectionMode; + set + { + _listBox.SelectedItems.Clear(); + this.RaiseAndSetIfChanged(ref _selectionMode, value); + } + } + + private string GenerateItem() => $"Item {_counter++}"; + } } } From 9e874529c6ef747105b76f1ed66f50b3579efcce Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Sat, 29 Jun 2019 18:40:51 +0300 Subject: [PATCH 3/5] Add `Add`, `Remove` buttons and `SelectionMode` combobox to TreeViewPage.xaml --- .../ControlCatalog/Pages/TreeViewPage.xaml | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/samples/ControlCatalog/Pages/TreeViewPage.xaml b/samples/ControlCatalog/Pages/TreeViewPage.xaml index c03edb8b03..1b01a38c60 100644 --- a/samples/ControlCatalog/Pages/TreeViewPage.xaml +++ b/samples/ControlCatalog/Pages/TreeViewPage.xaml @@ -6,16 +6,29 @@ Displays a hierachical tree of data. - - - - - - - + Margin="0,16,0,0" + HorizontalAlignment="Center" + Spacing="16"> + + + + + + + + + + + + + + + Single + Multiple + Toggle + AlwaysSelected + + From 6f58bb0e392081739453ac2fef67c93552b5fa55 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Sat, 29 Jun 2019 18:41:29 +0300 Subject: [PATCH 4/5] Implement functionality for added controls in TreeViewPage.xaml.cs --- .../ControlCatalog/Pages/ListBoxPage.xaml.cs | 2 +- .../ControlCatalog/Pages/TreeViewPage.xaml.cs | 93 +++++++++++++++++-- 2 files changed, 85 insertions(+), 10 deletions(-) diff --git a/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs b/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs index e1a615af4b..d6d48cd030 100644 --- a/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs +++ b/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs @@ -36,7 +36,7 @@ namespace ControlCatalog.Pages RemoveItemCommand = ReactiveCommand.Create(() => { - foreach (string selectedItem in listBox.SelectedItems) + foreach (string selectedItem in _listBox.SelectedItems) { Items.Remove(selectedItem); } diff --git a/samples/ControlCatalog/Pages/TreeViewPage.xaml.cs b/samples/ControlCatalog/Pages/TreeViewPage.xaml.cs index a83f9cf43f..cf6aa50db7 100644 --- a/samples/ControlCatalog/Pages/TreeViewPage.xaml.cs +++ b/samples/ControlCatalog/Pages/TreeViewPage.xaml.cs @@ -1,8 +1,9 @@ -using System.Collections; -using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; +using System.Reactive; using Avalonia.Controls; using Avalonia.Markup.Xaml; +using ReactiveUI; namespace ControlCatalog.Pages { @@ -10,8 +11,8 @@ namespace ControlCatalog.Pages { public TreeViewPage() { - this.InitializeComponent(); - DataContext = new Node().Children; + InitializeComponent(); + DataContext = new PageViewModel(this.Find("treeView")); } private void InitializeComponent() @@ -19,22 +20,96 @@ namespace ControlCatalog.Pages AvaloniaXamlLoader.Load(this); } - public class Node + private class PageViewModel : ReactiveObject { - private IList _children; + private readonly TreeView _treeView; + private SelectionMode _selectionMode; + + public PageViewModel(TreeView treeView) + { + _treeView = treeView; + + Node root = new Node(); + Items = root.Children; + + AddItemCommand = ReactiveCommand.Create(() => + { + Node selectedItem = _treeView.SelectedItems.Count > 0 ? (Node)_treeView.SelectedItems[0] : root; + selectedItem.AddNewItem(); + }); + + RemoveItemCommand = ReactiveCommand.Create(() => + { + foreach (Node selectedItem in _treeView.SelectedItems) + { + RecursiveRemove(Items, selectedItem); + } + + _treeView.SelectedItems.Clear(); + + 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 ReactiveCommand AddItemCommand { get; } + + public ReactiveCommand RemoveItemCommand { get; } + + public SelectionMode SelectionMode + { + get => _selectionMode; + set + { + _treeView.SelectedItems.Clear(); + this.RaiseAndSetIfChanged(ref _selectionMode, value); + } + } + } + + private class Node + { + private int _counter; + private ObservableCollection _children; + public string Header { get; private set; } - public IList Children + + public bool AreChildrenInitialized => _children != null; + + public ObservableCollection Children { get { if (_children == null) { - _children = Enumerable.Range(1, 10).Select(i => new Node() {Header = $"Item {i}"}) - .ToArray(); + _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++}"}; } } } From df6068604b69270f14c785465a7a703e9da3ed73 Mon Sep 17 00:00:00 2001 From: Ivan Kochurkin Date: Sat, 29 Jun 2019 23:10:13 +0300 Subject: [PATCH 5/5] Fix @Gillibald review notes: get rid of passing control to viewmodel, use binding instead --- samples/ControlCatalog/Pages/ListBoxPage.xaml | 2 +- .../ControlCatalog/Pages/ListBoxPage.xaml.cs | 16 ++++++------- .../ControlCatalog/Pages/TreeViewPage.xaml | 2 +- .../ControlCatalog/Pages/TreeViewPage.xaml.cs | 24 +++++++++---------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/samples/ControlCatalog/Pages/ListBoxPage.xaml b/samples/ControlCatalog/Pages/ListBoxPage.xaml index e7c81a28d4..49e9aafc4a 100644 --- a/samples/ControlCatalog/Pages/ListBoxPage.xaml +++ b/samples/ControlCatalog/Pages/ListBoxPage.xaml @@ -10,7 +10,7 @@ HorizontalAlignment="Center" Spacing="16"> - + diff --git a/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs b/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs index d6d48cd030..8a67766c76 100644 --- a/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs +++ b/samples/ControlCatalog/Pages/ListBoxPage.xaml.cs @@ -12,7 +12,7 @@ namespace ControlCatalog.Pages public ListBoxPage() { InitializeComponent(); - DataContext = new PageViewModel(this.Find("listBox")); + DataContext = new PageViewModel(); } private void InitializeComponent() @@ -22,29 +22,29 @@ namespace ControlCatalog.Pages private class PageViewModel : ReactiveObject { - private readonly ListBox _listBox; private int _counter; private SelectionMode _selectionMode; - public PageViewModel(ListBox listBox) + public PageViewModel() { - _listBox = listBox; - Items = new ObservableCollection(Enumerable.Range(1, 10).Select(i => GenerateItem())); + SelectedItems = new ObservableCollection(); AddItemCommand = ReactiveCommand.Create(() => Items.Add(GenerateItem())); RemoveItemCommand = ReactiveCommand.Create(() => { - foreach (string selectedItem in _listBox.SelectedItems) + while (SelectedItems.Count > 0) { - Items.Remove(selectedItem); + Items.Remove(SelectedItems[0]); } }); } public ObservableCollection Items { get; } + public ObservableCollection SelectedItems { get; } + public ReactiveCommand AddItemCommand { get; } public ReactiveCommand RemoveItemCommand { get; } @@ -54,7 +54,7 @@ namespace ControlCatalog.Pages get => _selectionMode; set { - _listBox.SelectedItems.Clear(); + SelectedItems.Clear(); this.RaiseAndSetIfChanged(ref _selectionMode, value); } } diff --git a/samples/ControlCatalog/Pages/TreeViewPage.xaml b/samples/ControlCatalog/Pages/TreeViewPage.xaml index 1b01a38c60..3a81e2ed02 100644 --- a/samples/ControlCatalog/Pages/TreeViewPage.xaml +++ b/samples/ControlCatalog/Pages/TreeViewPage.xaml @@ -10,7 +10,7 @@ HorizontalAlignment="Center" Spacing="16"> - + diff --git a/samples/ControlCatalog/Pages/TreeViewPage.xaml.cs b/samples/ControlCatalog/Pages/TreeViewPage.xaml.cs index cf6aa50db7..1f35f05f1d 100644 --- a/samples/ControlCatalog/Pages/TreeViewPage.xaml.cs +++ b/samples/ControlCatalog/Pages/TreeViewPage.xaml.cs @@ -12,7 +12,7 @@ namespace ControlCatalog.Pages public TreeViewPage() { InitializeComponent(); - DataContext = new PageViewModel(this.Find("treeView")); + DataContext = new PageViewModel(); } private void InitializeComponent() @@ -22,31 +22,29 @@ namespace ControlCatalog.Pages private class PageViewModel : ReactiveObject { - private readonly TreeView _treeView; private SelectionMode _selectionMode; - public PageViewModel(TreeView treeView) + public PageViewModel() { - _treeView = treeView; - Node root = new Node(); Items = root.Children; + SelectedItems = new ObservableCollection(); AddItemCommand = ReactiveCommand.Create(() => { - Node selectedItem = _treeView.SelectedItems.Count > 0 ? (Node)_treeView.SelectedItems[0] : root; - selectedItem.AddNewItem(); + Node parentItem = SelectedItems.Count > 0 ? SelectedItems[0] : root; + parentItem.AddNewItem(); }); RemoveItemCommand = ReactiveCommand.Create(() => { - foreach (Node selectedItem in _treeView.SelectedItems) + while (SelectedItems.Count > 0) { - RecursiveRemove(Items, selectedItem); + Node lastItem = SelectedItems[0]; + RecursiveRemove(Items, lastItem); + SelectedItems.Remove(lastItem); } - _treeView.SelectedItems.Clear(); - bool RecursiveRemove(ObservableCollection items, Node selectedItem) { if (items.Remove(selectedItem)) @@ -69,6 +67,8 @@ namespace ControlCatalog.Pages public ObservableCollection Items { get; } + public ObservableCollection SelectedItems { get; } + public ReactiveCommand AddItemCommand { get; } public ReactiveCommand RemoveItemCommand { get; } @@ -78,7 +78,7 @@ namespace ControlCatalog.Pages get => _selectionMode; set { - _treeView.SelectedItems.Clear(); + SelectedItems.Clear(); this.RaiseAndSetIfChanged(ref _selectionMode, value); } }