|
|
|
@ -5,6 +5,7 @@ using System.Collections.Specialized; |
|
|
|
using System.ComponentModel; |
|
|
|
using System.Diagnostics; |
|
|
|
using System.Linq; |
|
|
|
using System.Net.Http.Headers; |
|
|
|
using Avalonia.Collections; |
|
|
|
using Avalonia.Controls.Generators; |
|
|
|
using Avalonia.Controls.Utils; |
|
|
|
@ -503,32 +504,58 @@ namespace Avalonia.Controls.Primitives |
|
|
|
/// Selects all items in the control.
|
|
|
|
/// </summary>
|
|
|
|
protected void SelectAll() |
|
|
|
{ |
|
|
|
_selection.Clear(); |
|
|
|
|
|
|
|
for (var i = 0; i < ItemCount; ++i) |
|
|
|
{ |
|
|
|
_selection.Add(i); |
|
|
|
} |
|
|
|
|
|
|
|
UpdateSelectedItem(0, false); |
|
|
|
|
|
|
|
SyncSelection(); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Deselects all items in the control.
|
|
|
|
/// </summary>
|
|
|
|
protected void UnselectAll() => UpdateSelectedItem(-1); |
|
|
|
|
|
|
|
private void SyncSelection() |
|
|
|
{ |
|
|
|
UpdateSelectedItems(() => |
|
|
|
{ |
|
|
|
_selection.Clear(); |
|
|
|
var selection = _selection.Select(x => ElementAt(Items, x)).ToList(); |
|
|
|
var added = selection.Except(SelectedItems.Cast<object>()).ToList(); |
|
|
|
var removed = SelectedItems.Cast<object>().Except(selection).ToList(); |
|
|
|
|
|
|
|
for (var i = 0; i < ItemCount; ++i) |
|
|
|
foreach (var container in ItemContainerGenerator.Containers) |
|
|
|
{ |
|
|
|
_selection.Add(i); |
|
|
|
MarkItemSelected(container.Index, _selection.Contains(container.Index)); |
|
|
|
} |
|
|
|
|
|
|
|
UpdateSelectedItem(0, false); |
|
|
|
foreach (var i in added) |
|
|
|
{ |
|
|
|
SelectedItems.Add(i); |
|
|
|
} |
|
|
|
|
|
|
|
foreach (var container in ItemContainerGenerator.Containers) |
|
|
|
foreach (var i in removed) |
|
|
|
{ |
|
|
|
MarkItemSelected(container.Index, true); |
|
|
|
SelectedItems.Remove(i); |
|
|
|
} |
|
|
|
|
|
|
|
ResetSelectedItems(); |
|
|
|
if (added.Count > 0 || removed.Count > 0) |
|
|
|
{ |
|
|
|
var changed = new SelectionChangedEventArgs( |
|
|
|
SelectionChangedEvent, |
|
|
|
removed ?? Empty, |
|
|
|
added ?? Empty); |
|
|
|
RaiseEvent(changed); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Deselects all items in the control.
|
|
|
|
/// </summary>
|
|
|
|
protected void UnselectAll() => UpdateSelectedItem(-1); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Updates the selection for an item based on user interaction.
|
|
|
|
/// </summary>
|
|
|
|
@ -562,56 +589,36 @@ namespace Avalonia.Controls.Primitives |
|
|
|
} |
|
|
|
else if (range) |
|
|
|
{ |
|
|
|
UpdateSelectedItems(() => |
|
|
|
{ |
|
|
|
var start = SelectedIndex != -1 ? SelectedIndex : 0; |
|
|
|
var step = start < index ? 1 : -1; |
|
|
|
var start = SelectedIndex != -1 ? SelectedIndex : 0; |
|
|
|
var step = start < index ? 1 : -1; |
|
|
|
|
|
|
|
_selection.Clear(); |
|
|
|
_selection.Clear(); |
|
|
|
|
|
|
|
for (var i = start; i != index; i += step) |
|
|
|
{ |
|
|
|
_selection.Add(i); |
|
|
|
} |
|
|
|
|
|
|
|
_selection.Add(index); |
|
|
|
|
|
|
|
var first = Math.Min(start, index); |
|
|
|
var last = Math.Max(start, index); |
|
|
|
|
|
|
|
foreach (var container in ItemContainerGenerator.Containers) |
|
|
|
{ |
|
|
|
MarkItemSelected( |
|
|
|
container.Index, |
|
|
|
container.Index >= first && container.Index <= last); |
|
|
|
} |
|
|
|
for (var i = start; i != index; i += step) |
|
|
|
{ |
|
|
|
_selection.Add(i); |
|
|
|
} |
|
|
|
|
|
|
|
ResetSelectedItems(); |
|
|
|
}); |
|
|
|
_selection.Add(index); |
|
|
|
SyncSelection(); |
|
|
|
} |
|
|
|
else if (multi && toggle) |
|
|
|
{ |
|
|
|
UpdateSelectedItems(() => |
|
|
|
if (!_selection.Contains(index)) |
|
|
|
{ |
|
|
|
if (!_selection.Contains(index)) |
|
|
|
_selection.Add(index); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
_selection.Remove(index); |
|
|
|
|
|
|
|
if (index == _selectedIndex) |
|
|
|
{ |
|
|
|
_selection.Add(index); |
|
|
|
MarkItemSelected(index, true); |
|
|
|
SelectedItems.Add(ElementAt(Items, index)); |
|
|
|
UpdateSelectedItem(_selection.First(), false); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
_selection.Remove(index); |
|
|
|
MarkItemSelected(index, false); |
|
|
|
|
|
|
|
if (index == _selectedIndex) |
|
|
|
{ |
|
|
|
UpdateSelectedItem(_selection.First(), false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
SelectedItems.Remove(ElementAt(Items, index)); |
|
|
|
} |
|
|
|
}); |
|
|
|
SyncSelection(); |
|
|
|
} |
|
|
|
else if (toggle) |
|
|
|
{ |
|
|
|
@ -976,7 +983,8 @@ namespace Avalonia.Controls.Primitives |
|
|
|
var item = ElementAt(Items, index); |
|
|
|
var itemChanged = !Equals(item, oldItem); |
|
|
|
var added = -1; |
|
|
|
HashSet<int> removed = null; |
|
|
|
HashSet<int> removedIndexes = null; |
|
|
|
List<object> removedItems = null; |
|
|
|
|
|
|
|
_selectedIndex = index; |
|
|
|
_selectedItem = item; |
|
|
|
@ -985,7 +993,7 @@ namespace Avalonia.Controls.Primitives |
|
|
|
{ |
|
|
|
if (clear) |
|
|
|
{ |
|
|
|
removed = _selection.Clear(); |
|
|
|
removedIndexes = _selection.Clear(); |
|
|
|
} |
|
|
|
|
|
|
|
if (index != -1) |
|
|
|
@ -995,16 +1003,21 @@ namespace Avalonia.Controls.Primitives |
|
|
|
added = index; |
|
|
|
} |
|
|
|
|
|
|
|
if (removed?.Contains(index) == true) |
|
|
|
if (removedIndexes?.Contains(index) == true) |
|
|
|
{ |
|
|
|
removed.Remove(index); |
|
|
|
removedIndexes.Remove(index); |
|
|
|
added = -1; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
removedItems ??= new List<object>(); |
|
|
|
removedItems.Add(oldItem); |
|
|
|
} |
|
|
|
|
|
|
|
if (removed != null) |
|
|
|
if (removedIndexes != null) |
|
|
|
{ |
|
|
|
foreach (var i in removed) |
|
|
|
foreach (var i in removedIndexes) |
|
|
|
{ |
|
|
|
MarkItemSelected(i, false); |
|
|
|
} |
|
|
|
@ -1026,18 +1039,33 @@ namespace Avalonia.Controls.Primitives |
|
|
|
item); |
|
|
|
} |
|
|
|
|
|
|
|
if (removed != null && index != -1) |
|
|
|
if (removedIndexes != null && index != -1) |
|
|
|
{ |
|
|
|
removed.Remove(index); |
|
|
|
removedIndexes.Remove(index); |
|
|
|
} |
|
|
|
|
|
|
|
if (added != -1 || removed?.Count > 0) |
|
|
|
if (added != -1 || removedItems?.Count > 0 || removedIndexes?.Count > 0) |
|
|
|
{ |
|
|
|
ResetSelectedItems(); |
|
|
|
|
|
|
|
if (removedIndexes is object) |
|
|
|
{ |
|
|
|
removedItems ??= new List<object>(); |
|
|
|
|
|
|
|
foreach (var removed in removedIndexes) |
|
|
|
{ |
|
|
|
var i = ElementAt(Items, removed); |
|
|
|
|
|
|
|
if (!removedItems.Contains(i)) |
|
|
|
{ |
|
|
|
removedItems.Add(i); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var e = new SelectionChangedEventArgs( |
|
|
|
SelectionChangedEvent, |
|
|
|
removed?.Select(x => ElementAt(Items, x)).ToArray() ?? Array.Empty<object>(), |
|
|
|
(IList)removedItems ?? Array.Empty<object>(), |
|
|
|
added != -1 ? new[] { ElementAt(Items, added) } : Array.Empty<object>()); |
|
|
|
RaiseEvent(e); |
|
|
|
} |
|
|
|
|