Refactor ListBox Data

This commit is contained in:
chinboy
2025-10-29 11:32:59 +08:00
parent f729ff8994
commit 73a452f855
10 changed files with 381 additions and 93 deletions
@@ -1,15 +1,24 @@
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using Avalonia.Collections;
namespace AtomUI.Controls.Data;
internal interface ISelectOptionCollectionView: IEnumerable, INotifyCollectionChanged
internal interface IListBoxCollectionView: IEnumerable, INotifyCollectionChanged
{
CultureInfo Culture { get; set; }
bool Contains(object item);
IEnumerable SourceCollection { get; }
Func<object, bool>? Filter { get; set; }
bool CanFilter { get; }
bool CanSort { get; }
bool CanGroup { get; }
bool IsGrouping { get; }
int GroupingDepth { get; }
string GetGroupingPropertyNameAtDepth(int level);
IAvaloniaReadOnlyList<object>? Groups { get; }
SelectSortDescriptionCollection? SortDescriptions { get; }
SelectFilterDescriptionCollection? FilterDescriptions { get; }
bool IsEmpty { get; }
void Refresh();
@@ -0,0 +1,279 @@
// using System.Collections;
// using System.ComponentModel;
// using System.Globalization;
// using System.Reflection;
// using AtomUI.Controls.Data;
//
// namespace AtomUI.Controls;
//
// internal class SelectOptionCollectionView : IListBoxCollectionView, IList, INotifyPropertyChanged
// {
// #region 公共属性定义
//
//
//
// #endregion
//
// #region 公共事件定义
//
//
//
// #endregion
//
// #region 内部属性定义
//
//
//
// #endregion
//
// /// <summary>
// /// CultureInfo used in this DataGridCollectionView
// /// </summary>
// private CultureInfo _culture;
//
// /// <summary>
// /// Private accessor for the Monitor we use to prevent recursion
// /// </summary>
// private SimpleMonitor _currentChangedMonitor = new SimpleMonitor();
//
// /// <summary>
// /// The number of requests to defer Refresh()
// /// </summary>
// private int _deferLevel;
//
// /// <summary>
// /// Private accessor for the Filter
// /// </summary>
// private Func<object, bool>? _filter;
//
// /// <summary>
// /// Private accessor for the CollectionViewFlags
// /// </summary>
// private CollectionViewFlags _flags = CollectionViewFlags.ShouldProcessCollectionChanged;
//
// /// <summary>
// /// Private accessor for the Grouping data
// /// </summary>
// private ListBoxCollectionViewGroupRoot _group;
//
// /// <summary>
// /// Private accessor for the InternalList
// /// </summary>
// private IList _internalList;
//
// /// <summary>
// /// Keeps track of whether groups have been applied to the
// /// collection already or not. Note that this can still be set
// /// to false even though we specify a GroupDescription, as the
// /// collection may not have gone through the PrepareGroups function.
// /// </summary>
// private bool _isGrouping;
//
// /// <summary>
// /// Private accessor for indicating whether we want to point to the temporary grouping data for calculations
// /// </summary>
// private bool _isUsingTemporaryGroup;
//
// /// <summary>
// /// ConstructorInfo obtained from reflection for generating new items
// /// </summary>
// private ConstructorInfo? _itemConstructor;
//
// /// <summary>
// /// Whether we have the correct ConstructorInfo information for the ItemConstructor
// /// </summary>
// private bool _itemConstructorIsValid;
//
// /// <summary>
// /// The new item we are getting ready to add to the collection
// /// </summary>
// private object? _newItem;
//
// /// <summary>
// /// Whether the source needs to poll for changes
// /// (if it did not implement INotifyCollectionChanged)
// /// </summary>
// private bool _pollForChanges;
//
// /// <summary>
// /// Private accessor for the SortDescriptions
// /// </summary>
// private SelectSortDescriptionCollection? _sortDescriptions;
//
// /// <summary>
// /// Private accessor for the FilterDescriptions
// /// </summary>
// private SelectFilterDescriptionCollection? _filterDescriptions;
//
// [Flags]
// private enum CollectionViewFlags
// {
// /// <summary>
// /// Whether the list of items (after applying the sort and filters, if any)
// /// is already in the correct order for grouping.
// /// </summary>
// IsDataInGroupOrder = 0x01,
//
// /// <summary>
// /// Whether the source collection is already sorted according to the SortDescriptions collection
// /// </summary>
// IsDataSorted = 0x02,
//
// /// <summary>
// /// Whether we should process the collection changed event
// /// </summary>
// ShouldProcessCollectionChanged = 0x04,
//
// /// <summary>
// /// Whether we need to refresh
// /// </summary>
// NeedsRefresh = 0x10,
//
// /// <summary>
// /// Whether we cache the IsEmpty value
// /// </summary>
// CachedIsEmpty = 0x20,
//
// /// <summary>
// /// Indicates whether a page index change is in process or not
// /// </summary>
// IsPageChanging = 0x40,
//
// /// <summary>
// /// Whether we need to move to another page after EndDefer
// /// </summary>
// IsMoveToPageDeferred = 0x100,
//
// /// <summary>
// /// Whether we need to update the PageSize after EndDefer
// /// </summary>
// IsUpdatePageSizeDeferred = 0x200
// }
//
// /// <summary>
// /// A simple monitor class to help prevent re-entrant calls
// /// </summary>
// private class SimpleMonitor : IDisposable
// {
// /// <summary>
// /// Whether the monitor is entered
// /// </summary>
// private bool _entered;
//
// /// <summary>
// /// Gets a value indicating whether we have been entered or not
// /// </summary>
// public bool Busy => _entered;
//
// /// <summary>
// /// Sets a value indicating that we have been entered
// /// </summary>
// /// <returns>Boolean value indicating whether we were already entered</returns>
// public bool Enter()
// {
// if (_entered)
// {
// return false;
// }
//
// _entered = true;
// return true;
// }
//
// /// <summary>
// /// Cleanup method called when done using this class
// /// </summary>
// public void Dispose()
// {
// _entered = false;
// GC.SuppressFinalize(this);
// }
// }
//
// private class DeferHelper : IDisposable
// {
// /// <summary>
// /// Private reference to the CollectionView that created this DeferHelper
// /// </summary>
// private SelectOptionCollectionView? _collectionView;
//
// /// <summary>
// /// Initializes a new instance of the DeferHelper class
// /// </summary>
// /// <param name="collectionView">CollectionView that created this DeferHelper</param>
// public DeferHelper(SelectOptionCollectionView? collectionView)
// {
// _collectionView = collectionView;
// }
//
// /// <summary>
// /// Cleanup method called when done using this class
// /// </summary>
// public void Dispose()
// {
// if (_collectionView != null)
// {
// _collectionView.EndDefer();
// _collectionView = null;
// }
//
// GC.SuppressFinalize(this);
// }
// }
//
// /// <summary>
// /// Creates a comparer class that takes in a CultureInfo as a parameter,
// /// which it will use when comparing strings.
// /// </summary>
// private class CultureSensitiveComparer : IComparer<object>
// {
// /// <summary>
// /// Private accessor for the CultureInfo of our comparer
// /// </summary>
// private CultureInfo _culture;
//
// /// <summary>
// /// Creates a comparer which will respect the CultureInfo
// /// that is passed in when comparing strings.
// /// </summary>
// /// <param name="culture">The CultureInfo to use in string comparisons</param>
// public CultureSensitiveComparer(CultureInfo? culture)
// {
// _culture = culture ?? CultureInfo.InvariantCulture;
// }
//
// /// <summary>
// /// Compares two objects and returns a value indicating whether one is less than, equal to or greater than the other.
// /// </summary>
// /// <param name="x">first item to compare</param>
// /// <param name="y">second item to compare</param>
// /// <returns>Negative number if x is less than y, zero if equal, and a positive number if x is greater than y</returns>
// /// <remarks>
// /// Compares the 2 items using the specified CultureInfo for string and using the default object comparer for all other objects.
// /// </remarks>
// public int Compare(object? x, object? y)
// {
// if (x == null)
// {
// if (y != null)
// {
// return -1;
// }
//
// return 0;
// }
//
// if (y == null)
// {
// return 1;
// }
//
// // at this point x and y are not null
// if (x is string xString && y is string yString)
// {
// return _culture.CompareInfo.Compare(xString, yString);
// }
// return Comparer<object>.Default.Compare(x, y);
// }
// }
// }
@@ -3,7 +3,7 @@ using Avalonia.Collections;
namespace AtomUI.Controls.Data;
public abstract class SelectCollectionViewGroup : INotifyPropertyChanged
public abstract class ListBoxCollectionViewGroup : INotifyPropertyChanged
{
private int _itemCount;
public object Key { get; }
@@ -21,10 +21,10 @@ public abstract class SelectCollectionViewGroup : INotifyPropertyChanged
}
}
internal abstract SelectCollectionViewGroupInternal? Parent { get; }
internal abstract SelectGroupDescription? GroupBy { get; set; }
internal abstract ListBoxCollectionViewGroupInternal? Parent { get; }
internal abstract ListBoxGroupDescription? GroupBy { get; set; }
protected SelectCollectionViewGroup(object key)
protected ListBoxCollectionViewGroup(object key)
{
Key = key;
ProtectedItems = new AvaloniaList<object>();
@@ -5,24 +5,24 @@ using Avalonia;
namespace AtomUI.Controls.Data;
internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
internal class ListBoxCollectionViewGroupInternal : ListBoxCollectionViewGroup
{
/// <summary>
/// GroupDescription used to define how to group the items
/// </summary>
private SelectGroupDescription? _groupBy;
private ListBoxGroupDescription? _groupBy;
/// <summary>
/// Parent group of this SelectCollectionViewGroupInternal
/// Parent group of this ListBoxCollectionViewGroupInternal
/// </summary>
private readonly SelectCollectionViewGroupInternal? _parentGroup;
private readonly ListBoxCollectionViewGroupInternal? _parentGroup;
/// <summary>
/// Used for detecting stale enumerators
/// </summary>
private int _version;
public SelectCollectionViewGroupInternal(object key, SelectCollectionViewGroupInternal? parent)
public ListBoxCollectionViewGroupInternal(object key, ListBoxCollectionViewGroupInternal? parent)
: base(key)
{
_parentGroup = parent;
@@ -32,7 +32,7 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
internal int FullCount { get; set; }
internal override SelectGroupDescription? GroupBy
internal override ListBoxGroupDescription? GroupBy
{
get => _groupBy;
set
@@ -86,7 +86,7 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
// look for first item, child by child
for (int k = 0, n = Items.Count; k < n; ++k)
{
if (!(Items[k] is SelectCollectionViewGroupInternal subgroup))
if (!(Items[k] is ListBoxCollectionViewGroupInternal subgroup))
{
// child is an item - return it
return Items[k];
@@ -111,7 +111,7 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
}
}
internal override SelectCollectionViewGroupInternal? Parent => _parentGroup;
internal override ListBoxCollectionViewGroupInternal? Parent => _parentGroup;
/// <summary>
/// Adds the specified item to the collection
@@ -166,7 +166,7 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
for (index = low; index < high; ++index)
{
object seed1 = (ProtectedItems[index] is SelectCollectionViewGroupInternal subgroup)
object seed1 = (ProtectedItems[index] is ListBoxCollectionViewGroupInternal subgroup)
? subgroup.SeedItem
: ProtectedItems[index];
if (seed1 == AvaloniaProperty.UnsetValue)
@@ -230,7 +230,7 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
{
for (int k = 0, n = Items.Count; k < n; ++k)
{
if (Items[k] is SelectCollectionViewGroupInternal subgroup)
if (Items[k] is ListBoxCollectionViewGroupInternal subgroup)
{
// current item is a group - either drill in, or skip over
if (index < subgroup.ItemCount)
@@ -267,7 +267,7 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
int result = 0;
// accumulate the number of predecessors at each level
for (SelectCollectionViewGroupInternal? group = this;
for (ListBoxCollectionViewGroupInternal? group = this;
group != null;
item = group, group = group.Parent, index = -1)
{
@@ -282,7 +282,7 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
}
// accumulate leaf count
SelectCollectionViewGroupInternal? subgroup = group.Items[k] as SelectCollectionViewGroupInternal;
ListBoxCollectionViewGroupInternal? subgroup = group.Items[k] as ListBoxCollectionViewGroupInternal;
result += subgroup?.ItemCount ?? 1;
}
}
@@ -301,7 +301,7 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
int leaves = 0; // number of leaves we've passed over so far
for (int k = 0, n = Items.Count; k < n; ++k)
{
if (Items[k] is SelectCollectionViewGroupInternal subgroup)
if (Items[k] is ListBoxCollectionViewGroupInternal subgroup)
{
int subgroupIndex = subgroup.LeafIndexOf(item);
if (subgroupIndex < 0)
@@ -357,13 +357,13 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
/// Removes an empty group from the PagedCollectionView grouping
/// </summary>
/// <param name="group">Empty subgroup to remove</param>
private static void RemoveEmptyGroup(SelectCollectionViewGroupInternal group)
private static void RemoveEmptyGroup(ListBoxCollectionViewGroupInternal group)
{
SelectCollectionViewGroupInternal? parent = group.Parent;
ListBoxCollectionViewGroupInternal? parent = group.Parent;
if (parent != null)
{
SelectGroupDescription? groupBy = parent.GroupBy;
ListBoxGroupDescription? groupBy = parent.GroupBy;
int index = parent.ProtectedItems.IndexOf(group);
// remove the subgroup unless it is one of the explicit groups
@@ -381,9 +381,9 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
/// <param name="delta">Delta to change count by</param>
protected void ChangeCounts(object item, int delta)
{
bool changeLeafCount = !(item is SelectCollectionViewGroup);
bool changeLeafCount = !(item is ListBoxCollectionViewGroup);
for (SelectCollectionViewGroupInternal? group = this;
for (ListBoxCollectionViewGroupInternal? group = this;
group != null;
group = group._parentGroup)
{
@@ -412,7 +412,7 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
private class LeafEnumerator : IEnumerator
{
private object? _current; // current item
private SelectCollectionViewGroupInternal? _group; // parent group
private ListBoxCollectionViewGroupInternal? _group; // parent group
private int _index; // current index into Items
private IEnumerator? _subEnum; // enumerator over current subgroup
private int _version; // parent group's version at ctor
@@ -421,7 +421,7 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
/// Initializes a new instance of the LeafEnumerator class.
/// </summary>
/// <param name="group">CollectionViewGroupInternal that uses the enumerator</param>
public LeafEnumerator(SelectCollectionViewGroupInternal group)
public LeafEnumerator(ListBoxCollectionViewGroupInternal group)
{
_group = group;
DoReset(); // don't call virtual Reset in ctor
@@ -470,8 +470,8 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
return false;
}
SelectCollectionViewGroupInternal? subgroup =
_group.Items[_index] as SelectCollectionViewGroupInternal;
ListBoxCollectionViewGroupInternal? subgroup =
_group.Items[_index] as ListBoxCollectionViewGroupInternal;
if (subgroup == null)
{
// current item is a leaf - it's the new Current
@@ -595,8 +595,8 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
// / <summary>
// / This comparer is used to insert an item into a group in a position consistent
// / with a given SelectCollectionViewGroupRoot. We will only use this when dealing with
// / a temporary SelectCollectionViewGroupRoot that points to the correct grouping of the
// / with a given ListBoxCollectionViewGroupRoot. We will only use this when dealing with
// / a temporary ListBoxCollectionViewGroupRoot that points to the correct grouping of the
// / entire collection, and we have paging that requires us to keep the paged group
// / consistent with the order of items in the temporary group.
// / </summary>
@@ -604,10 +604,10 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
{
/// <summary>
/// Constructor for the CollectionViewGroupComparer that takes
/// in an SelectCollectionViewGroupRoot.
/// in an ListBoxCollectionViewGroupRoot.
/// </summary>
/// <param name="group">SelectCollectionViewGroupRoot used to compare on</param>
internal CollectionViewGroupComparer(SelectCollectionViewGroupRoot group)
/// <param name="group">ListBoxCollectionViewGroupRoot used to compare on</param>
internal CollectionViewGroupComparer(ListBoxCollectionViewGroupRoot group)
{
_group = group;
_index = 0;
@@ -624,11 +624,11 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
/// <summary>
/// Sets our group to a new instance of a
/// SelectCollectionViewGroupRoot being passed in
/// ListBoxCollectionViewGroupRoot being passed in
/// and resets the index.
/// </summary>
/// <param name="group">SelectCollectionViewGroupRoot used to compare on</param>
internal void ResetGroup(SelectCollectionViewGroupRoot group)
/// <param name="group">ListBoxCollectionViewGroupRoot used to compare on</param>
internal void ResetGroup(ListBoxCollectionViewGroupRoot group)
{
_group = group;
_index = 0;
@@ -669,6 +669,6 @@ internal class SelectCollectionViewGroupInternal : SelectCollectionViewGroup
}
private int _index;
private SelectCollectionViewGroupRoot _group;
private ListBoxCollectionViewGroupRoot _group;
}
}
@@ -6,7 +6,7 @@ using Avalonia.Collections;
namespace AtomUI.Controls.Data;
internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal, INotifyCollectionChanged
internal class ListBoxCollectionViewGroupRoot : ListBoxCollectionViewGroupInternal, INotifyCollectionChanged
{
/// <summary>
/// String constant used for the Root Name
@@ -21,12 +21,12 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// <summary>
/// Private accessor for the top level GroupDescription
/// </summary>
private static SelectGroupDescription? _topLevelGroupDescription;
private static ListBoxGroupDescription? _topLevelGroupDescription;
/// <summary>
/// Private accessor for an ObservableCollection containing group descriptions
/// </summary>
private readonly AvaloniaList<SelectGroupDescription> _groupBy = new ();
private readonly AvaloniaList<ListBoxGroupDescription> _groupBy = new ();
/// <summary>
/// Indicates whether the list of items (after applying the sort and filters, if any)
@@ -37,7 +37,7 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// <summary>
/// Private accessor for the owning ICollectionView
/// </summary>
private readonly ISelectOptionCollectionView _view;
private readonly IListBoxCollectionView _view;
/// <summary>
/// Raise this event when the (grouped) view changes
@@ -50,11 +50,11 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
internal event EventHandler? GroupDescriptionChanged;
/// <summary>
/// Initializes a new instance of the SelectCollectionViewGroupRoot class.
/// Initializes a new instance of the ListBoxCollectionViewGroupRoot class.
/// </summary>
/// <param name="view">CollectionView that contains this grouping</param>
/// <param name="isDataInGroupOrder">True if items are already in correct order for grouping</param>
internal SelectCollectionViewGroupRoot(ISelectOptionCollectionView view, bool isDataInGroupOrder)
internal ListBoxCollectionViewGroupRoot(IListBoxCollectionView view, bool isDataInGroupOrder)
: base(RootName, null)
{
_view = view;
@@ -64,7 +64,7 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// <summary>
/// Gets the description of grouping, indexed by level.
/// </summary>
public virtual AvaloniaList<SelectGroupDescription> GroupDescriptions => _groupBy;
public virtual AvaloniaList<ListBoxGroupDescription> GroupDescriptions => _groupBy;
/// <summary>
/// Gets or sets the current IComparer being used
@@ -229,16 +229,16 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// <param name="level">The level of grouping.</param>
/// <param name="key">Name of subgroup to add to</param>
/// <param name="loading">Whether we are currently loading</param>
private void AddToSubgroup(object item, SelectCollectionViewGroupInternal group, int level, object key,
private void AddToSubgroup(object item, ListBoxCollectionViewGroupInternal group, int level, object key,
bool loading)
{
SelectCollectionViewGroupInternal? subgroup;
ListBoxCollectionViewGroupInternal? subgroup;
int index = (_isDataInGroupOrder) ? group.LastIndex : 0;
// find the desired subgroup
for (int n = group.Items.Count; index < n; ++index)
{
subgroup = group.Items[index] as SelectCollectionViewGroupInternal;
subgroup = group.Items[index] as ListBoxCollectionViewGroupInternal;
if (subgroup == null)
{
continue; // skip children that are not groups
@@ -253,7 +253,7 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
}
// the item didn't match any subgroups. Create a new subgroup and add the item.
subgroup = new SelectCollectionViewGroupInternal(key, group);
subgroup = new ListBoxCollectionViewGroupInternal(key, group);
InitializeGroup(subgroup, level + 1, item);
if (loading)
@@ -282,7 +282,7 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// <param name="group">Group to add item to</param>
/// <param name="level">The level of grouping</param>
/// <param name="loading">Whether we are currently loading</param>
private void AddToSubgroups(object item, SelectCollectionViewGroupInternal group, int level, bool loading)
private void AddToSubgroups(object item, ListBoxCollectionViewGroupInternal group, int level, bool loading)
{
object? key = GetGroupKey(item, group.GroupBy, level);
@@ -322,7 +322,7 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
}
}
public virtual Func<SelectCollectionViewGroup, int, SelectGroupDescription>? GroupBySelector { get; set; }
public virtual Func<ListBoxCollectionViewGroup, int, ListBoxGroupDescription>? GroupBySelector { get; set; }
/// <summary>
/// Returns the description of how to divide the given group into subgroups
@@ -330,10 +330,10 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// <param name="group">CollectionViewGroup to get group description from</param>
/// <param name="level">The level of grouping</param>
/// <returns>GroupDescription of how to divide the given group</returns>
private SelectGroupDescription? GetGroupDescription(SelectCollectionViewGroup group, int level)
private ListBoxGroupDescription? GetGroupDescription(ListBoxCollectionViewGroup group, int level)
{
SelectGroupDescription? result = null;
SelectCollectionViewGroup? targetGroup = group;
ListBoxGroupDescription? result = null;
ListBoxCollectionViewGroup? targetGroup = group;
if (targetGroup == this)
{
targetGroup = null;
@@ -359,7 +359,7 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// <param name="groupDescription">GroupDescription for the group</param>
/// <param name="level">The level of grouping</param>
/// <returns>Group names for the specified item</returns>
private object? GetGroupKey(object item, SelectGroupDescription? groupDescription, int level)
private object? GetGroupKey(object item, ListBoxGroupDescription? groupDescription, int level)
{
if (groupDescription != null)
{
@@ -374,10 +374,10 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// <param name="group">Group to initialize</param>
/// <param name="level">The level of grouping</param>
/// <param name="seedItem">The seed item to compare with to see where to insert</param>
private void InitializeGroup(SelectCollectionViewGroupInternal group, int level, object? seedItem)
private void InitializeGroup(ListBoxCollectionViewGroupInternal group, int level, object? seedItem)
{
// set the group description for dividing the group into subgroups
SelectGroupDescription? groupDescription = GetGroupDescription(group, level);
ListBoxGroupDescription? groupDescription = GetGroupDescription(group, level);
group.GroupBy = groupDescription;
// create subgroups for each of the explicit names
@@ -386,7 +386,7 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
{
for (int k = 0, n = keys.Count; k < n; ++k)
{
SelectCollectionViewGroupInternal subgroup = new SelectCollectionViewGroupInternal(keys[k], group);
ListBoxCollectionViewGroupInternal subgroup = new ListBoxCollectionViewGroupInternal(keys[k], group);
InitializeGroup(subgroup, level + 1, seedItem);
group.Add(subgroup);
}
@@ -401,7 +401,7 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// <param name="group">Group to remove item from</param>
/// <param name="item">Item to remove</param>
/// <returns>True if item could not be removed</returns>
private bool RemoveFromGroupDirectly(SelectCollectionViewGroupInternal group, object item)
private bool RemoveFromGroupDirectly(ListBoxCollectionViewGroupInternal group, object item)
{
int leafIndex = group.Remove(item, true);
if (leafIndex >= 0)
@@ -421,15 +421,15 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// <param name="level">The level of grouping</param>
/// <param name="key">Name of item to remove</param>
/// <returns>Return true if the item was not in one of the subgroups it was supposed to be.</returns>
private bool RemoveFromSubgroup(object item, SelectCollectionViewGroupInternal group, int level, object key)
private bool RemoveFromSubgroup(object item, ListBoxCollectionViewGroupInternal group, int level, object key)
{
bool itemIsMissing = false;
SelectCollectionViewGroupInternal? subGroup;
ListBoxCollectionViewGroupInternal? subGroup;
// find the desired subgroup
for (int index = 0, n = group.Items.Count; index < n; ++index)
{
subGroup = group.Items[index] as SelectCollectionViewGroupInternal;
subGroup = group.Items[index] as ListBoxCollectionViewGroupInternal;
if (subGroup == null)
{
continue; // skip children that are not groups
@@ -457,7 +457,7 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// <param name="group">Group to remove item from</param>
/// <param name="level">The level of grouping</param>
/// <returns>Return true if the item was not in one of the subgroups it was supposed to be.</returns>
private bool RemoveFromSubgroups(object item, SelectCollectionViewGroupInternal group, int level)
private bool RemoveFromSubgroups(object item, ListBoxCollectionViewGroupInternal group, int level)
{
bool itemIsMissing = false;
object? key = GetGroupKey(item, group.GroupBy, level);
@@ -502,7 +502,7 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// </summary>
/// <param name="group">Group to remove item from</param>
/// <param name="item">Item to remove</param>
private void RemoveItemFromSubgroupsByExhaustiveSearch(SelectCollectionViewGroupInternal group, object item)
private void RemoveItemFromSubgroupsByExhaustiveSearch(ListBoxCollectionViewGroupInternal group, object item)
{
// try to remove the item from the direct children
// this function only returns true if it failed to remove from group directly
@@ -513,7 +513,7 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
// (loop runs backwards in case an entire group is deleted)
for (int k = group.Items.Count - 1; k >= 0; --k)
{
if (group.Items[k] is SelectCollectionViewGroupInternal subgroup)
if (group.Items[k] is ListBoxCollectionViewGroupInternal subgroup)
{
RemoveItemFromSubgroupsByExhaustiveSearch(subgroup, item);
}
@@ -524,7 +524,7 @@ internal class SelectCollectionViewGroupRoot : SelectCollectionViewGroupInternal
/// <summary>
/// TopLevelGroupDescription class
/// </summary>
private class TopLevelGroupDescription : SelectGroupDescription
private class TopLevelGroupDescription : ListBoxGroupDescription
{
/// <summary>
/// Initializes a new instance of the TopLevelGroupDescription class.
@@ -1,12 +1,12 @@
namespace AtomUI.Controls.Data;
internal class SelectDefaultFilter
internal class ListBoxDefaultFilter
{
private readonly WeakReference<ISelectOptionCollectionView> CollectionViewRef;
private readonly WeakReference<IListBoxCollectionView> CollectionViewRef;
public SelectDefaultFilter(ISelectOptionCollectionView collectionView)
public ListBoxDefaultFilter(IListBoxCollectionView collectionView)
{
CollectionViewRef = new WeakReference<ISelectOptionCollectionView>(collectionView);
CollectionViewRef = new WeakReference<IListBoxCollectionView>(collectionView);
}
public bool Filter(object value)
@@ -31,7 +31,7 @@ internal class SelectDefaultFilter
return false;
}
public static implicit operator Func<object, bool>(SelectDefaultFilter filter)
public static implicit operator Func<object, bool>(ListBoxDefaultFilter filter)
{
return filter.Filter;
}
@@ -4,7 +4,7 @@ using Avalonia.Collections;
namespace AtomUI.Controls.Data;
public class SelectFilterDescription
public class ListBoxFilterDescription
{
public string? PropertyPath { get; set; }
public bool HasPropertyPath => !string.IsNullOrEmpty(PropertyPath);
@@ -79,4 +79,4 @@ public class SelectFilterDescription
}
}
public class SelectFilterDescriptionCollection : AvaloniaList<SelectFilterDescription> {}
public class SelectFilterDescriptionCollection : AvaloniaList<ListBoxFilterDescription> {}
@@ -4,11 +4,11 @@ using Avalonia.Collections;
namespace AtomUI.Controls.Data;
public abstract class SelectGroupDescription : INotifyPropertyChanged
public abstract class ListBoxGroupDescription : INotifyPropertyChanged
{
public AvaloniaList<object> GroupKeys { get; }
public SelectGroupDescription()
public ListBoxGroupDescription()
{
GroupKeys = new AvaloniaList<object>();
GroupKeys.CollectionChanged += (sender, e) => OnPropertyChanged(new PropertyChangedEventArgs(nameof(GroupKeys)));
@@ -5,14 +5,14 @@ using Avalonia.Data.Converters;
namespace AtomUI.Controls.Data;
public class SelectPathGroupDescription : SelectGroupDescription
public class ListBoxPathGroupDescription : ListBoxGroupDescription
{
private string _propertyPath;
private Type? _propertyType;
private IValueConverter? _valueConverter;
private StringComparison _stringComparison = StringComparison.Ordinal;
public SelectPathGroupDescription(string propertyPath)
public ListBoxPathGroupDescription(string propertyPath)
{
_propertyPath = propertyPath;
}
@@ -6,7 +6,7 @@ using Avalonia.Collections;
namespace AtomUI.Controls.Data;
public abstract class SelectSortDescription
public abstract class ListBoxSortDescription
{
public virtual string? PropertyPath => null;
@@ -26,7 +26,7 @@ public abstract class SelectSortDescription
return seq.ThenBy(o => o, Comparer);
}
public virtual SelectSortDescription SwitchSortDirection()
public virtual ListBoxSortDescription SwitchSortDirection()
{
return this;
}
@@ -47,19 +47,19 @@ public abstract class SelectSortDescription
return propertyValue;
}
public static SelectSortDescription FromPath(string propertyPath, ListSortDirection direction = ListSortDirection.Ascending, CultureInfo? culture = null)
public static ListBoxSortDescription FromPath(string propertyPath, ListSortDirection direction = ListSortDirection.Ascending, CultureInfo? culture = null)
{
return new SelectPathSortDescription(propertyPath, direction, null, culture);
return new ListBoxPathSortDescription(propertyPath, direction, null, culture);
}
public static SelectSortDescription FromPath(string propertyPath, ListSortDirection direction, IComparer comparer)
public static ListBoxSortDescription FromPath(string propertyPath, ListSortDirection direction, IComparer comparer)
{
return new SelectPathSortDescription(propertyPath, direction, comparer, null);
return new ListBoxPathSortDescription(propertyPath, direction, comparer, null);
}
public static SelectSortDescription FromComparer(IComparer comparer, ListSortDirection direction = ListSortDirection.Ascending)
public static ListBoxSortDescription FromComparer(IComparer comparer, ListSortDirection direction = ListSortDirection.Ascending)
{
return new SelectComparerSortDescription(comparer, direction);
return new ListBoxComparerSortDescription(comparer, direction);
}
/// <summary>
@@ -119,7 +119,7 @@ public abstract class SelectSortDescription
}
}
private class SelectPathSortDescription : SelectSortDescription
private class ListBoxPathSortDescription : ListBoxSortDescription
{
private readonly ListSortDirection _direction;
private readonly string _propertyPath;
@@ -153,7 +153,7 @@ public abstract class SelectSortDescription
public override IComparer<object> Comparer => _comparer.Value;
public override ListSortDirection Direction => _direction;
public SelectPathSortDescription(string propertyPath, ListSortDirection direction, IComparer? internalComparer,
public ListBoxPathSortDescription(string propertyPath, ListSortDirection direction, IComparer? internalComparer,
CultureInfo? culture)
{
_propertyPath = propertyPath;
@@ -164,7 +164,7 @@ public abstract class SelectSortDescription
_comparer = new Lazy<IComparer<object>>(() => Comparer<object>.Create(Compare));
}
private SelectPathSortDescription(SelectPathSortDescription inner, ListSortDirection direction)
private ListBoxPathSortDescription(ListBoxPathSortDescription inner, ListSortDirection direction)
{
_propertyPath = inner._propertyPath;
_direction = direction;
@@ -297,17 +297,17 @@ public abstract class SelectSortDescription
return seq.ThenBy(GetValue, InternalComparer);
}
public override SelectSortDescription SwitchSortDirection()
public override ListBoxSortDescription SwitchSortDirection()
{
var newDirection = _direction == ListSortDirection.Ascending
? ListSortDirection.Descending
: ListSortDirection.Ascending;
return new SelectPathSortDescription(this, newDirection);
return new ListBoxPathSortDescription(this, newDirection);
}
}
}
public class SelectComparerSortDescription : SelectSortDescription
public class ListBoxComparerSortDescription : ListBoxSortDescription
{
private readonly IComparer _innerComparer;
private readonly ListSortDirection _direction;
@@ -316,7 +316,7 @@ public class SelectComparerSortDescription : SelectSortDescription
public IComparer SourceComparer => _innerComparer;
public override IComparer<object> Comparer => _comparer;
public override ListSortDirection Direction => _direction;
public SelectComparerSortDescription(IComparer comparer, ListSortDirection direction)
public ListBoxComparerSortDescription(IComparer comparer, ListSortDirection direction)
{
_innerComparer = comparer;
_direction = direction;
@@ -335,11 +335,11 @@ public class SelectComparerSortDescription : SelectSortDescription
return result;
}
public override SelectSortDescription SwitchSortDirection()
public override ListBoxSortDescription SwitchSortDirection()
{
var newDirection = _direction == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending;
return new SelectComparerSortDescription(_innerComparer, newDirection);
return new ListBoxComparerSortDescription(_innerComparer, newDirection);
}
}
public class SelectSortDescriptionCollection : AvaloniaList<SelectSortDescription> {}
public class SelectSortDescriptionCollection : AvaloniaList<ListBoxSortDescription> {}