Browse Source

Expose pre/post collection changed events.

Instead of implementing `ICollectionChangedListener` on `SelectionNodeBase`. We may want to expose this publicly at some point.
pull/10589/head
Steven Kirk 4 years ago
parent
commit
21574f5607
  1. 39
      src/Avalonia.Controls/ItemsSourceView.cs
  2. 38
      src/Avalonia.Controls/Selection/SelectionNodeBase.cs

39
src/Avalonia.Controls/ItemsSourceView.cs

@ -27,6 +27,7 @@ namespace Avalonia.Controls
private readonly IList _inner; private readonly IList _inner;
private NotifyCollectionChangedEventHandler? _collectionChanged; private NotifyCollectionChangedEventHandler? _collectionChanged;
private NotifyCollectionChangedEventHandler? _preCollectionChanged;
private NotifyCollectionChangedEventHandler? _postCollectionChanged; private NotifyCollectionChangedEventHandler? _postCollectionChanged;
private bool _listening; private bool _listening;
@ -70,7 +71,7 @@ namespace Avalonia.Controls
/// Gets a value that indicates whether the items source can provide a unique key for each item. /// Gets a value that indicates whether the items source can provide a unique key for each item.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// TODO: Not yet implemented in Avalonia. /// Not implemented in Avalonia, preserved here for ItemsRepeater's usage.
/// </remarks> /// </remarks>
internal bool HasKeyIndexMapping => false; internal bool HasKeyIndexMapping => false;
@ -92,6 +93,25 @@ namespace Avalonia.Controls
} }
} }
/// <summary>
/// Occurs when a collection has finished changing and all <see cref="CollectionChanged"/>
/// event handlers have been notified.
/// </summary>
internal event NotifyCollectionChangedEventHandler? PreCollectionChanged
{
add
{
AddListenerIfNecessary();
_preCollectionChanged += value;
}
remove
{
_preCollectionChanged -= value;
RemoveListenerIfNecessary();
}
}
/// <summary> /// <summary>
/// Occurs when a collection has finished changing and all <see cref="CollectionChanged"/> /// Occurs when a collection has finished changing and all <see cref="CollectionChanged"/>
/// event handlers have been notified. /// event handlers have been notified.
@ -229,6 +249,7 @@ namespace Avalonia.Controls
void ICollectionChangedListener.PreChanged(INotifyCollectionChanged sender, NotifyCollectionChangedEventArgs e) void ICollectionChangedListener.PreChanged(INotifyCollectionChanged sender, NotifyCollectionChangedEventArgs e)
{ {
_preCollectionChanged?.Invoke(this, e);
} }
void ICollectionChangedListener.Changed(INotifyCollectionChanged sender, NotifyCollectionChangedEventArgs e) void ICollectionChangedListener.Changed(INotifyCollectionChanged sender, NotifyCollectionChangedEventArgs e)
@ -241,22 +262,6 @@ namespace Avalonia.Controls
_postCollectionChanged?.Invoke(this, e); _postCollectionChanged?.Invoke(this, e);
} }
internal void AddListener(ICollectionChangedListener listener)
{
if (Inner is INotifyCollectionChanged incc)
{
CollectionChangedEventManager.Instance.AddListener(incc, listener);
}
}
internal void RemoveListener(ICollectionChangedListener listener)
{
if (Inner is INotifyCollectionChanged incc)
{
CollectionChangedEventManager.Instance.RemoveListener(incc, listener);
}
}
/// <summary> /// <summary>
/// Retrieves the index of the item that has the specified unique identifier (key). /// Retrieves the index of the item that has the specified unique identifier (key).
/// </summary> /// </summary>

38
src/Avalonia.Controls/Selection/SelectionNodeBase.cs

@ -2,7 +2,6 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using Avalonia.Controls.Utils;
namespace Avalonia.Controls.Selection namespace Avalonia.Controls.Selection
{ {
@ -10,7 +9,7 @@ namespace Avalonia.Controls.Selection
/// Base class for selection models. /// Base class for selection models.
/// </summary> /// </summary>
/// <typeparam name="T">The type of the element being selected.</typeparam> /// <typeparam name="T">The type of the element being selected.</typeparam>
public abstract class SelectionNodeBase<T> : ICollectionChangedListener public abstract class SelectionNodeBase<T>
{ {
private IEnumerable? _source; private IEnumerable? _source;
private bool _rangesEnabled; private bool _rangesEnabled;
@ -24,12 +23,28 @@ namespace Avalonia.Controls.Selection
get => _source; get => _source;
set set
{ {
void OnPreChanged(object? sender, NotifyCollectionChangedEventArgs e) => OnSourceCollectionChangeStarted();
void OnChanged(object? sender, NotifyCollectionChangedEventArgs e) => OnSourceCollectionChanged(e);
void OnPostChanged(object? sender, NotifyCollectionChangedEventArgs e) => OnSourceCollectionChangeFinished();
if (_source != value) if (_source != value)
{ {
ItemsView?.RemoveListener(this); if (ItemsView is not null)
{
ItemsView.PreCollectionChanged -= OnPreChanged;
ItemsView.CollectionChanged -= OnChanged;
ItemsView.PostCollectionChanged -= OnPostChanged;
}
_source = value; _source = value;
ItemsView = value is not null ? ItemsSourceView.GetOrCreate<T>(value) : null; ItemsView = value is not null ? ItemsSourceView.GetOrCreate<T>(value) : null;
ItemsView?.AddListener(this);
if (ItemsView is not null)
{
ItemsView.PreCollectionChanged += OnPreChanged;
ItemsView.CollectionChanged += OnChanged;
ItemsView.PostCollectionChanged += OnPostChanged;
}
} }
} }
} }
@ -73,21 +88,6 @@ namespace Avalonia.Controls.Selection
} }
} }
void ICollectionChangedListener.PreChanged(INotifyCollectionChanged sender, NotifyCollectionChangedEventArgs e)
{
OnSourceCollectionChangeStarted();
}
void ICollectionChangedListener.Changed(INotifyCollectionChanged sender, NotifyCollectionChangedEventArgs e)
{
OnSourceCollectionChanged(e);
}
void ICollectionChangedListener.PostChanged(INotifyCollectionChanged sender, NotifyCollectionChangedEventArgs e)
{
OnSourceCollectionChangeFinished();
}
/// <summary> /// <summary>
/// Called when the source collection starts changing. /// Called when the source collection starts changing.
/// </summary> /// </summary>

Loading…
Cancel
Save