|
|
@ -105,32 +105,21 @@ namespace Avalonia.Controls |
|
|
get => _selectedItem; |
|
|
get => _selectedItem; |
|
|
set |
|
|
set |
|
|
{ |
|
|
{ |
|
|
SetAndRaise(SelectedItemProperty, ref _selectedItem, |
|
|
SetAndRaise(SelectedItemProperty, ref _selectedItem, value); |
|
|
(object val, ref object backing, Action<Action> notifyWrapper) => |
|
|
|
|
|
{ |
|
|
|
|
|
var old = backing; |
|
|
|
|
|
backing = val; |
|
|
|
|
|
|
|
|
|
|
|
notifyWrapper(() => |
|
|
|
|
|
RaisePropertyChanged( |
|
|
|
|
|
SelectedItemProperty, |
|
|
|
|
|
old, |
|
|
|
|
|
val)); |
|
|
|
|
|
|
|
|
|
|
|
if (val != null) |
|
|
if (value != null) |
|
|
{ |
|
|
{ |
|
|
if (SelectedItems.Count != 1 || SelectedItems[0] != val) |
|
|
if (SelectedItems.Count != 1 || SelectedItems[0] != value) |
|
|
{ |
|
|
{ |
|
|
_syncingSelectedItems = true; |
|
|
_syncingSelectedItems = true; |
|
|
SelectSingleItem(val); |
|
|
SelectSingleItem(value); |
|
|
_syncingSelectedItems = false; |
|
|
_syncingSelectedItems = false; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else if (SelectedItems.Count > 0) |
|
|
else if (SelectedItems.Count > 0) |
|
|
{ |
|
|
{ |
|
|
SelectedItems.Clear(); |
|
|
SelectedItems.Clear(); |
|
|
} |
|
|
} |
|
|
}, value); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -164,6 +153,48 @@ namespace Avalonia.Controls |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Expands the specified <see cref="TreeViewItem"/> all descendent <see cref="TreeViewItem"/>s.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="item">The item to expand.</param>
|
|
|
|
|
|
public void ExpandSubTree(TreeViewItem item) |
|
|
|
|
|
{ |
|
|
|
|
|
item.IsExpanded = true; |
|
|
|
|
|
|
|
|
|
|
|
var panel = item.Presenter.Panel; |
|
|
|
|
|
|
|
|
|
|
|
if (panel != null) |
|
|
|
|
|
{ |
|
|
|
|
|
foreach (var child in panel.Children) |
|
|
|
|
|
{ |
|
|
|
|
|
if (child is TreeViewItem treeViewItem) |
|
|
|
|
|
{ |
|
|
|
|
|
ExpandSubTree(treeViewItem); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Selects all items in the <see cref="TreeView"/>.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <remarks>
|
|
|
|
|
|
/// Note that this method only selects nodes currently visible due to their parent nodes
|
|
|
|
|
|
/// being expanded: it does not expand nodes.
|
|
|
|
|
|
/// </remarks>
|
|
|
|
|
|
public void SelectAll() |
|
|
|
|
|
{ |
|
|
|
|
|
SynchronizeItems(SelectedItems, ItemContainerGenerator.Index.Items); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Deselects all items in the <see cref="TreeView"/>.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void UnselectAll() |
|
|
|
|
|
{ |
|
|
|
|
|
SelectedItems.Clear(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Subscribes to the <see cref="SelectedItems"/> CollectionChanged event, if any.
|
|
|
/// Subscribes to the <see cref="SelectedItems"/> CollectionChanged event, if any.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
@ -409,7 +440,7 @@ namespace Avalonia.Controls |
|
|
|
|
|
|
|
|
if (this.SelectionMode == SelectionMode.Multiple && Match(keymap.SelectAll)) |
|
|
if (this.SelectionMode == SelectionMode.Multiple && Match(keymap.SelectAll)) |
|
|
{ |
|
|
{ |
|
|
SynchronizeItems(SelectedItems, ItemContainerGenerator.Index.Items); |
|
|
SelectAll(); |
|
|
e.Handled = true; |
|
|
e.Handled = true; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -479,7 +510,8 @@ namespace Avalonia.Controls |
|
|
e.Source, |
|
|
e.Source, |
|
|
true, |
|
|
true, |
|
|
(e.InputModifiers & InputModifiers.Shift) != 0, |
|
|
(e.InputModifiers & InputModifiers.Shift) != 0, |
|
|
(e.InputModifiers & InputModifiers.Control) != 0); |
|
|
(e.InputModifiers & InputModifiers.Control) != 0, |
|
|
|
|
|
e.MouseButton == MouseButton.Right); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -490,11 +522,13 @@ namespace Avalonia.Controls |
|
|
/// <param name="select">Whether the item should be selected or unselected.</param>
|
|
|
/// <param name="select">Whether the item should be selected or unselected.</param>
|
|
|
/// <param name="rangeModifier">Whether the range modifier is enabled (i.e. shift key).</param>
|
|
|
/// <param name="rangeModifier">Whether the range modifier is enabled (i.e. shift key).</param>
|
|
|
/// <param name="toggleModifier">Whether the toggle modifier is enabled (i.e. ctrl key).</param>
|
|
|
/// <param name="toggleModifier">Whether the toggle modifier is enabled (i.e. ctrl key).</param>
|
|
|
|
|
|
/// <param name="rightButton">Whether the event is a right-click.</param>
|
|
|
protected void UpdateSelectionFromContainer( |
|
|
protected void UpdateSelectionFromContainer( |
|
|
IControl container, |
|
|
IControl container, |
|
|
bool select = true, |
|
|
bool select = true, |
|
|
bool rangeModifier = false, |
|
|
bool rangeModifier = false, |
|
|
bool toggleModifier = false) |
|
|
bool toggleModifier = false, |
|
|
|
|
|
bool rightButton = false) |
|
|
{ |
|
|
{ |
|
|
var item = ItemContainerGenerator.Index.ItemFromContainer(container); |
|
|
var item = ItemContainerGenerator.Index.ItemFromContainer(container); |
|
|
|
|
|
|
|
|
@ -515,7 +549,14 @@ namespace Avalonia.Controls |
|
|
var multi = (mode & SelectionMode.Multiple) != 0; |
|
|
var multi = (mode & SelectionMode.Multiple) != 0; |
|
|
var range = multi && selectedContainer != null && rangeModifier; |
|
|
var range = multi && selectedContainer != null && rangeModifier; |
|
|
|
|
|
|
|
|
if (!toggle && !range) |
|
|
if (rightButton) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!SelectedItems.Contains(item)) |
|
|
|
|
|
{ |
|
|
|
|
|
SelectSingleItem(item); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else if (!toggle && !range) |
|
|
{ |
|
|
{ |
|
|
SelectSingleItem(item); |
|
|
SelectSingleItem(item); |
|
|
} |
|
|
} |
|
|
@ -684,6 +725,7 @@ namespace Avalonia.Controls |
|
|
/// <param name="select">Whether the container should be selected or unselected.</param>
|
|
|
/// <param name="select">Whether the container should be selected or unselected.</param>
|
|
|
/// <param name="rangeModifier">Whether the range modifier is enabled (i.e. shift key).</param>
|
|
|
/// <param name="rangeModifier">Whether the range modifier is enabled (i.e. shift key).</param>
|
|
|
/// <param name="toggleModifier">Whether the toggle modifier is enabled (i.e. ctrl key).</param>
|
|
|
/// <param name="toggleModifier">Whether the toggle modifier is enabled (i.e. ctrl key).</param>
|
|
|
|
|
|
/// <param name="rightButton">Whether the event is a right-click.</param>
|
|
|
/// <returns>
|
|
|
/// <returns>
|
|
|
/// True if the event originated from a container that belongs to the control; otherwise
|
|
|
/// True if the event originated from a container that belongs to the control; otherwise
|
|
|
/// false.
|
|
|
/// false.
|
|
|
@ -692,13 +734,14 @@ namespace Avalonia.Controls |
|
|
IInteractive eventSource, |
|
|
IInteractive eventSource, |
|
|
bool select = true, |
|
|
bool select = true, |
|
|
bool rangeModifier = false, |
|
|
bool rangeModifier = false, |
|
|
bool toggleModifier = false) |
|
|
bool toggleModifier = false, |
|
|
|
|
|
bool rightButton = false) |
|
|
{ |
|
|
{ |
|
|
var container = GetContainerFromEventSource(eventSource); |
|
|
var container = GetContainerFromEventSource(eventSource); |
|
|
|
|
|
|
|
|
if (container != null) |
|
|
if (container != null) |
|
|
{ |
|
|
{ |
|
|
UpdateSelectionFromContainer(container, select, rangeModifier, toggleModifier); |
|
|
UpdateSelectionFromContainer(container, select, rangeModifier, toggleModifier, rightButton); |
|
|
return true; |
|
|
return true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|