csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
5.2 KiB
151 lines
5.2 KiB
using System;
|
|
using System.Collections;
|
|
using System.Collections.Specialized;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using Avalonia.Collections;
|
|
|
|
namespace Avalonia.Controls
|
|
{
|
|
/// <summary>
|
|
/// Holds the list of items that constitute the content of an <see cref="ItemsControl"/>.
|
|
/// </summary>
|
|
public class ItemCollection : ItemsSourceView, IList
|
|
{
|
|
// Suppress "Avoid zero-length array allocations": This is a sentinel value and must be unique.
|
|
#pragma warning disable CA1825
|
|
private static readonly object?[] s_uninitialized = new object?[0];
|
|
#pragma warning restore CA1825
|
|
|
|
private Mode _mode;
|
|
|
|
internal ItemCollection()
|
|
: base(s_uninitialized)
|
|
{
|
|
}
|
|
|
|
public new object? this[int index]
|
|
{
|
|
get => base[index];
|
|
set => WritableSource[index] = value;
|
|
}
|
|
|
|
public bool IsReadOnly => _mode == Mode.ItemsSource;
|
|
|
|
internal event EventHandler? SourceChanged;
|
|
|
|
/// <summary>
|
|
/// Adds an item to the <see cref="ItemsControl"/>.
|
|
/// </summary>
|
|
/// <param name="value">The item to add to the collection.</param>
|
|
/// <returns>
|
|
/// The position into which the new element was inserted, or -1 to indicate that
|
|
/// the item was not inserted into the collection.
|
|
/// </returns>
|
|
/// <exception cref="InvalidOperationException">
|
|
/// The collection is in ItemsSource mode.
|
|
/// </exception>
|
|
public int Add(object? value) => WritableSource.Add(value);
|
|
|
|
/// <summary>
|
|
/// Clears the collection and releases the references on all items currently in the
|
|
/// collection.
|
|
/// </summary>
|
|
/// <exception cref="InvalidOperationException">
|
|
/// The collection is in ItemsSource mode.
|
|
/// </exception>
|
|
public void Clear() => WritableSource.Clear();
|
|
|
|
/// <summary>
|
|
/// Inserts an element into the collection at the specified index.
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index at which to insert the item.</param>
|
|
/// <param name="value">The item to insert.</param>
|
|
/// <exception cref="InvalidOperationException">
|
|
/// The collection is in ItemsSource mode.
|
|
/// </exception>
|
|
public void Insert(int index, object? value) => WritableSource.Insert(index, value);
|
|
|
|
/// <summary>
|
|
/// Removes the item at the specified index of the collection or view.
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index of the item to remove.</param>
|
|
/// <exception cref="InvalidOperationException">
|
|
/// The collection is in ItemsSource mode.
|
|
/// </exception>
|
|
public void RemoveAt(int index) => WritableSource.RemoveAt(index);
|
|
|
|
/// <summary>
|
|
/// Removes the specified item reference from the collection or view.
|
|
/// </summary>
|
|
/// <param name="value">The object to remove.</param>
|
|
/// <returns>True if the item was removed; otherwise false.</returns>
|
|
/// <exception cref="InvalidOperationException">
|
|
/// The collection is in ItemsSource mode.
|
|
/// </exception>
|
|
public bool Remove(object? value)
|
|
{
|
|
var c = Count;
|
|
WritableSource.Remove(value);
|
|
return Count < c;
|
|
}
|
|
|
|
int IList.Add(object? value) => Add(value);
|
|
void IList.Clear() => Clear();
|
|
void IList.Insert(int index, object? value) => Insert(index, value);
|
|
void IList.RemoveAt(int index) => RemoveAt(index);
|
|
|
|
private IList WritableSource
|
|
{
|
|
get
|
|
{
|
|
if (IsReadOnly)
|
|
ThrowIsItemsSource();
|
|
if (Source == s_uninitialized)
|
|
SetSource(CreateDefaultCollection());
|
|
return Source;
|
|
}
|
|
}
|
|
|
|
internal void SetItemsSource(IEnumerable? value)
|
|
{
|
|
if (_mode != Mode.ItemsSource && Count > 0)
|
|
throw new InvalidOperationException(
|
|
"Items collection must be empty before using ItemsSource.");
|
|
|
|
_mode = value is not null ? Mode.ItemsSource : Mode.Items;
|
|
SetSource(value ?? CreateDefaultCollection());
|
|
}
|
|
|
|
private new void SetSource(IEnumerable source)
|
|
{
|
|
var oldSource = Source;
|
|
|
|
base.SetSource(source);
|
|
|
|
if (oldSource.Count > 0)
|
|
RaiseCollectionChanged(new(NotifyCollectionChangedAction.Remove, oldSource, 0));
|
|
if (Source.Count > 0)
|
|
RaiseCollectionChanged(new(NotifyCollectionChangedAction.Add, Source, 0));
|
|
SourceChanged?.Invoke(this, EventArgs.Empty);
|
|
}
|
|
|
|
private static AvaloniaList<object?> CreateDefaultCollection()
|
|
{
|
|
return new() { ResetBehavior = ResetBehavior.Remove };
|
|
}
|
|
|
|
[DoesNotReturn]
|
|
private static void ThrowIsItemsSource()
|
|
{
|
|
throw new InvalidOperationException(
|
|
"Operation is not valid while ItemsSource is in use." +
|
|
"Access and modify elements with ItemsControl.ItemsSource instead.");
|
|
}
|
|
|
|
private enum Mode
|
|
{
|
|
Items,
|
|
ItemsSource,
|
|
}
|
|
}
|
|
}
|
|
|