-
Notifications
You must be signed in to change notification settings - Fork 743
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Implemented SelectedItemsVector and SelectedTreeNodeVector
- Loading branch information
1 parent
bb40a3d
commit de9e4a3
Showing
4 changed files
with
221 additions
and
262 deletions.
There are no files selected for viewing
92 changes: 92 additions & 0 deletions
92
src/Uno.UI/Microsoft/UI/Xaml/Controls/TreeView/SelectedItemsVector.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Windows.Foundation.Collections; | ||
|
||
namespace Microsoft.UI.Xaml.Controls | ||
{ | ||
//// Similiar to SelectedNodesVector above, we need to make decisions before the item is inserted or removed. | ||
//// we can't use vector change events because the event already happened when event hander gets called. | ||
internal class SelectedItemsVector : ObservableVector<object> | ||
{ | ||
private TreeViewViewModel m_viewModel; | ||
|
||
public void SetViewModel(TreeViewViewModel viewModel) | ||
{ | ||
m_viewModel = viewModel; | ||
} | ||
|
||
internal void Append(object item) => InsertAt(Count, item); | ||
|
||
internal void InsertAt(int index, object item) | ||
{ | ||
if (!Contains(item)) | ||
{ | ||
GetVectorInnerImpl().Insert(index, item); | ||
|
||
// Keep SelectedNodes and SelectedItems in sync | ||
var viewModel = m_viewModel; | ||
if (viewModel != null) | ||
{ | ||
var selectedNodes = viewModel.SelectedNodes; | ||
if (selectedNodes.Count != Count) | ||
{ | ||
var listControl = viewModel.ListControl; | ||
if (listControl != null) | ||
{ | ||
var node = listControl.NodeFromItem(item); | ||
if (node != null) | ||
{ | ||
selectedNodes.Insert(index, node); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
internal void SetAt(int index, object item) | ||
{ | ||
RemoveAt(index); | ||
InsertAt(index, item); | ||
} | ||
|
||
public override void RemoveAt(int index) | ||
{ | ||
GetVectorInnerImpl().RemoveAt(index); | ||
|
||
// Keep SelectedNodes and SelectedItems in sync | ||
var viewModel = m_viewModel; | ||
if (viewModel != null) | ||
{ | ||
var selectedNodes = viewModel.SelectedNodes; | ||
if (Count != selectedNodes.Count) | ||
{ | ||
selectedNodes.RemoveAt(index); | ||
} | ||
} | ||
} | ||
|
||
internal void RemoveAtEnd() => RemoveAt(Count - 1); | ||
|
||
internal void ReplaceAll(IEnumerable<object> items) | ||
{ | ||
Clear(); | ||
|
||
foreach (var node in items) | ||
{ | ||
Append(node); | ||
} | ||
} | ||
|
||
public override void Clear() | ||
{ | ||
while (Count > 0) | ||
{ | ||
RemoveAtEnd(); | ||
} | ||
} | ||
} | ||
} |
127 changes: 127 additions & 0 deletions
127
src/Uno.UI/Microsoft/UI/Xaml/Controls/TreeView/SelectedTreeNodeVector.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
using System.Collections.Generic; | ||
using Microsoft.UI.Xaml.Controls; | ||
using Windows.Foundation.Collections; | ||
|
||
namespace Microsoft.UI.Xaml.Controls | ||
{ | ||
// Need to update node selection states on UI before vector changes. | ||
// Listen on vector change events don't solve the problem because the event already happened when the event handler gets called. | ||
// i.e. the node is alreay gone when we get to ItemRemoved callback. | ||
internal class SelectedTreeNodeVector : ObservableVector<TreeViewNode> | ||
{ | ||
TreeViewViewModel m_viewModel = null; | ||
|
||
private void UpdateSelection(TreeViewNode node, TreeNodeSelectionState state) | ||
{ | ||
if (node.SelectionState != state) | ||
{ | ||
var viewModel = m_viewModel; | ||
|
||
if (viewModel != null) | ||
{ | ||
viewModel.UpdateSelection(node, state); | ||
viewModel.NotifyContainerOfSelectionChange(node, state); | ||
} | ||
} | ||
} | ||
|
||
public void SetViewModel(TreeViewViewModel viewModel) | ||
{ | ||
m_viewModel = viewModel; | ||
} | ||
|
||
internal void Append(TreeViewNode node) => InsertAt(Count, node); | ||
|
||
public override void Add(TreeViewNode node) => Append(node); | ||
|
||
internal void InsertAt(int index, TreeViewNode node) | ||
{ | ||
if (!Contains(node)) | ||
{ | ||
// UpdateSelection will call InsertAtCore | ||
UpdateSelection(node, TreeNodeSelectionState.Selected); | ||
} | ||
} | ||
|
||
public override void Insert(int index, TreeViewNode node) => InsertAt(index, node); | ||
|
||
internal void SetAt(int index, TreeViewNode node) | ||
{ | ||
RemoveAt(index); | ||
InsertAt(index, node); | ||
} | ||
|
||
public override TreeViewNode this[int index] | ||
{ | ||
get => base[index]; | ||
set => SetAt(index, value); | ||
} | ||
|
||
public override void RemoveAt(int index) | ||
{ | ||
var inner = GetVectorInnerImpl(); | ||
var oldNode = inner[index]; | ||
// UpdateNodeSelection will call RemoveAtCore | ||
UpdateSelection(oldNode, TreeNodeSelectionState.UnSelected); | ||
} | ||
|
||
internal void RemoveAtEnd() => RemoveAt(Count - 1); | ||
|
||
internal void ReplaceAll(IEnumerable<TreeViewNode> nodes) | ||
{ | ||
Clear(); | ||
|
||
foreach (var node in nodes) | ||
{ | ||
Append(node); | ||
} | ||
} | ||
|
||
public override void Clear() | ||
{ | ||
while (Count > 0) | ||
{ | ||
RemoveAtEnd(); | ||
} | ||
} | ||
|
||
// Default write methods will trigger TreeView visual updates. | ||
// If you want to update vector content without notifying TreeViewNodes, use "core" version of the methods. | ||
internal void InsertAtCore(int index, TreeViewNode node) | ||
{ | ||
GetVectorInnerImpl().Insert(index, node); | ||
|
||
// Keep SelectedItems and SelectedNodes in sync | ||
var viewModel = m_viewModel; | ||
if (viewModel != null) | ||
{ | ||
var selectedItems = viewModel.SelectedItems; | ||
if (selectedItems.Count != Count) | ||
{ | ||
var listControl = viewModel.ListControl; | ||
var item = listControl?.ItemFromNode(node); | ||
if (item != null) | ||
{ | ||
selectedItems.Insert(index, item); | ||
} | ||
} | ||
} | ||
} | ||
|
||
internal void RemoveAtCore(int index) | ||
{ | ||
GetVectorInnerImpl().RemoveAt(index); | ||
|
||
// Keep SelectedItems and SelectedNodes in sync | ||
var viewModel = m_viewModel; | ||
if (viewModel != null) | ||
{ | ||
var selectedItems = viewModel.SelectedItems; | ||
if (Count != selectedItems.Count) | ||
{ | ||
selectedItems.RemoveAt(index); | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.