Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Use ItemsRepeater as base for ItemsPresenter #3388

Closed
wants to merge 9 commits into from
17 changes: 16 additions & 1 deletion samples/ControlCatalog/Pages/ListBoxPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,23 @@
HorizontalAlignment="Center"
Spacing="16">
<StackPanel Orientation="Vertical" Spacing="8">
<ListBox Items="{Binding Items}" SelectedItem="{Binding SelectedItem}" AutoScrollToSelectedItem="True" SelectedItems="{Binding SelectedItems}" SelectionMode="{Binding SelectionMode}" Width="250" Height="350"></ListBox>
<ListBox Items="{Binding Items}"
Layout="{Binding Layout}"
SelectedItem="{Binding SelectedItem}"
AutoScrollToSelectedItem="True"
SelectedItems="{Binding SelectedItems}"
SelectionMode="{Binding SelectionMode}"
ScrollViewer.VerticalScrollBarVisibility="{Binding VerticalScroll}"
ScrollViewer.HorizontalScrollBarVisibility="{Binding HorizontalScroll}"
Width="250" Height="350"/>

<ComboBox SelectedIndex="{Binding LayoutType}">
<ComboBoxItem>Stack - Vertical</ComboBoxItem>
<ComboBoxItem>Stack - Horizontal</ComboBoxItem>
<ComboBoxItem>UniformGrid - Vertical</ComboBoxItem>
<ComboBoxItem>UniformGrid - Horizontal</ComboBoxItem>
</ComboBox>

<Button Command="{Binding AddItemCommand}">Add</Button>

<Button Command="{Binding RemoveItemCommand}">Remove</Button>
Expand Down
63 changes: 2 additions & 61 deletions samples/ControlCatalog/Pages/ListBoxPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Reactive;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using ControlCatalog.ViewModels;
using ReactiveUI;

namespace ControlCatalog.Pages
Expand All @@ -13,72 +14,12 @@ public class ListBoxPage : UserControl
public ListBoxPage()
{
InitializeComponent();
DataContext = new PageViewModel();
DataContext = new ListBoxPageViewModel();
}

private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}

private class PageViewModel : ReactiveObject
{
private int _counter;
private SelectionMode _selectionMode;

public PageViewModel()
{
Items = new ObservableCollection<string>(Enumerable.Range(1, 10000).Select(i => GenerateItem()));
SelectedItems = new ObservableCollection<string>();

AddItemCommand = ReactiveCommand.Create(() => Items.Add(GenerateItem()));

RemoveItemCommand = ReactiveCommand.Create(() =>
{
while (SelectedItems.Count > 0)
{
Items.Remove(SelectedItems[0]);
}
});

SelectRandomItemCommand = ReactiveCommand.Create(() =>
{
var random = new Random();

SelectedItem = Items[random.Next(Items.Count - 1)];
});
}

public ObservableCollection<string> Items { get; }

private string _selectedItem;

public string SelectedItem
{
get { return _selectedItem; }
set { this.RaiseAndSetIfChanged(ref _selectedItem, value); }
}


public ObservableCollection<string> SelectedItems { get; }

public ReactiveCommand<Unit, Unit> AddItemCommand { get; }

public ReactiveCommand<Unit, Unit> RemoveItemCommand { get; }

public ReactiveCommand<Unit, Unit> SelectRandomItemCommand { get; }

public SelectionMode SelectionMode
{
get => _selectionMode;
set
{
SelectedItems.Clear();
this.RaiseAndSetIfChanged(ref _selectionMode, value);
}
}

private string GenerateItem() => $"Item {_counter++.ToString()}";
}
}
}
8 changes: 7 additions & 1 deletion samples/ControlCatalog/Pages/TreeViewPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
HorizontalAlignment="Center"
Spacing="16">
<StackPanel Orientation="Vertical" Spacing="8">
<TreeView Items="{Binding Items}" SelectedItems="{Binding SelectedItems}" SelectionMode="{Binding SelectionMode}" Width="250" Height="350">
<TreeView Name="treeView"
Items="{Binding Items}"
SelectedItems="{Binding SelectedItems}"
SelectionMode="{Binding SelectionMode}"
Width="250"
Height="350">
<TreeView.ItemTemplate>
<TreeDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Header}"/>
Expand All @@ -28,6 +33,7 @@
<ComboBoxItem>Toggle</ComboBoxItem>
<ComboBoxItem>AlwaysSelected</ComboBoxItem>
</ComboBox>
<TextBlock Text="{Binding ContainerCount, StringFormat=\{0\} Containers Materialized}"/>
</StackPanel>
</StackPanel>
</StackPanel>
Expand Down
115 changes: 24 additions & 91 deletions samples/ControlCatalog/Pages/TreeViewPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,115 +1,48 @@
using System.Collections.ObjectModel;
using System;
using System.Linq;
using System.Reactive;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using ReactiveUI;
using Avalonia.Threading;
using Avalonia.VisualTree;
using ControlCatalog.ViewModels;

namespace ControlCatalog.Pages
{
public class TreeViewPage : UserControl
{
private TreeView _treeView;
private DispatcherTimer _timer;

public TreeViewPage()
{
InitializeComponent();
DataContext = new PageViewModel();
_treeView = this.FindControl<TreeView>("treeView");
_timer = new DispatcherTimer(TimeSpan.FromSeconds(1), DispatcherPriority.Background, TimerTick);
DataContext = new TreeViewPageViewModel();
}

private void InitializeComponent()
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
AvaloniaXamlLoader.Load(this);
base.OnAttachedToVisualTree(e);
_timer.Start();
}

private class PageViewModel : ReactiveObject
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
private SelectionMode _selectionMode;

public PageViewModel()
{
Node root = new Node();
Items = root.Children;
SelectedItems = new ObservableCollection<Node>();

AddItemCommand = ReactiveCommand.Create(() =>
{
Node parentItem = SelectedItems.Count > 0 ? SelectedItems[0] : root;
parentItem.AddNewItem();
});

RemoveItemCommand = ReactiveCommand.Create(() =>
{
while (SelectedItems.Count > 0)
{
Node lastItem = SelectedItems[0];
RecursiveRemove(Items, lastItem);
SelectedItems.Remove(lastItem);
}

bool RecursiveRemove(ObservableCollection<Node> 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<Node> Items { get; }

public ObservableCollection<Node> SelectedItems { get; }

public ReactiveCommand<Unit, Unit> AddItemCommand { get; }

public ReactiveCommand<Unit, Unit> RemoveItemCommand { get; }

public SelectionMode SelectionMode
{
get => _selectionMode;
set
{
SelectedItems.Clear();
this.RaiseAndSetIfChanged(ref _selectionMode, value);
}
}
base.OnDetachedFromVisualTree(e);
_timer.Stop();
}

private class Node
private void InitializeComponent()
{
private int _counter;
private ObservableCollection<Node> _children;

public string Header { get; private set; }

public bool AreChildrenInitialized => _children != null;

public ObservableCollection<Node> Children
{
get
{
if (_children == null)
{
_children = new ObservableCollection<Node>(Enumerable.Range(1, 10).Select(i => CreateNewNode()));
}
return _children;
}
}

public void AddNewItem() => Children.Add(CreateNewNode());

public override string ToString() => Header;
AvaloniaXamlLoader.Load(this);
}

private Node CreateNewNode() => new Node {Header = $"Item {_counter++}"};
private void TimerTick(object sender, EventArgs e)
{
var vm = (TreeViewPageViewModel)DataContext;
vm.ContainerCount = _treeView.GetVisualDescendants().OfType<TreeViewItem>().Count();
}
}
}
124 changes: 124 additions & 0 deletions samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Layout;
using ReactiveUI;

namespace ControlCatalog.ViewModels
{
public enum LayoutType
{
StackVertical,
StackHorizontal,
UniformGridHorizontal,
UniformGridVertical,
}

public class ListBoxPageViewModel :ReactiveObject
{
private readonly ObservableAsPropertyHelper<AttachedLayout> _layout;
private readonly ObservableAsPropertyHelper<ScrollBarVisibility> _horizontalScroll;
private readonly ObservableAsPropertyHelper<ScrollBarVisibility> _verticalScroll;
private int _counter;
private LayoutType _layoutType;
private SelectionMode _selectionMode;
private string _selectedItem;

public ListBoxPageViewModel()
{
Items = new ObservableCollection<string>(Enumerable.Range(1, 10000).Select(i => GenerateItem()));
SelectedItems = new ObservableCollection<string>();

_layout = this.WhenAnyValue(x => x.LayoutType)
.Select(CreateLayout)
.ToProperty(this, x => x.Layout);

_horizontalScroll = this.WhenAnyValue(x => x.LayoutType)
.Select(x => (((int)x) % 2) == 0 ? ScrollBarVisibility.Disabled : ScrollBarVisibility.Auto)
.ToProperty(this, x => x.HorizontalScroll);

_verticalScroll = this.WhenAnyValue(x => x.LayoutType)
.Select(x => (((int)x) % 2) != 0 ? ScrollBarVisibility.Disabled : ScrollBarVisibility.Auto)
.ToProperty(this, x => x.VerticalScroll);

AddItemCommand = ReactiveCommand.Create(() => Items.Add(GenerateItem()));

RemoveItemCommand = ReactiveCommand.Create(() =>
{
while (SelectedItems.Count > 0)
{
Items.Remove(SelectedItems[0]);
}
});

SelectRandomItemCommand = ReactiveCommand.Create(() =>
{
var random = new Random();

SelectedItem = Items[random.Next(Items.Count - 1)];
});
}

public ObservableCollection<string> Items { get; }
public AttachedLayout Layout => _layout.Value;
public ScrollBarVisibility HorizontalScroll => _horizontalScroll.Value;
public ScrollBarVisibility VerticalScroll => _verticalScroll.Value;
public ObservableCollection<string> SelectedItems { get; }
public ReactiveCommand<Unit, Unit> AddItemCommand { get; }
public ReactiveCommand<Unit, Unit> RemoveItemCommand { get; }
public ReactiveCommand<Unit, Unit> SelectRandomItemCommand { get; }

public LayoutType LayoutType
{
get => _layoutType;
set => this.RaiseAndSetIfChanged(ref _layoutType, value);
}

public string SelectedItem
{
get => _selectedItem;
set => this.RaiseAndSetIfChanged(ref _selectedItem, value);
}

public SelectionMode SelectionMode
{
get => _selectionMode;
set
{
SelectedItems.Clear();
this.RaiseAndSetIfChanged(ref _selectionMode, value);
}
}

private string GenerateItem() => $"Item {_counter++.ToString()}";

private static AttachedLayout CreateLayout(LayoutType type)
{
switch (type)
{
case LayoutType.StackVertical:
return new StackLayout { Orientation = Orientation.Vertical };
case LayoutType.StackHorizontal:
return new StackLayout { Orientation = Orientation.Horizontal };
case LayoutType.UniformGridVertical:
return new UniformGridLayout
{
MinItemWidth = 70,
Orientation = Orientation.Vertical
};
case LayoutType.UniformGridHorizontal:
return new UniformGridLayout
{
MinItemWidth = 70,
Orientation = Orientation.Horizontal
};
default:
throw new NotSupportedException();
}
}
}
}
Loading