feat: scroll to select.
This commit is contained in:
@@ -46,16 +46,6 @@ public class Anchor: ItemsControl
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ScrollToAnchor(string anchorId)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
if (TargetContainer is null)
|
|
||||||
return;
|
|
||||||
var target = TargetContainer.GetVisualDescendants().FirstOrDefault(a=>Anchor.GetAnchorId(a) == anchorId);
|
|
||||||
if (target is null) return;
|
|
||||||
ScrollToAnchor(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
private CancellationTokenSource _cts = new();
|
private CancellationTokenSource _cts = new();
|
||||||
private bool _scrollingFromSelection = false;
|
private bool _scrollingFromSelection = false;
|
||||||
|
|
||||||
@@ -109,7 +99,29 @@ public class Anchor: ItemsControl
|
|||||||
|
|
||||||
public void InvalidatePositions()
|
public void InvalidatePositions()
|
||||||
{
|
{
|
||||||
|
InvalidateAnchorPositions();
|
||||||
|
MarkSelectedContainerByPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<(string, double)> _positions = [];
|
||||||
|
|
||||||
|
internal void InvalidateAnchorPositions()
|
||||||
|
{
|
||||||
|
if (TargetContainer is null) return;
|
||||||
|
var items = TargetContainer.GetVisualDescendants().Where(a => GetAnchorId(a) is not null);
|
||||||
|
List<(string, double)> positions = new List<(string, double)>();
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
var anchorId = GetAnchorId(item);
|
||||||
|
if (anchorId is null) continue;
|
||||||
|
var position = item.TransformToVisual(TargetContainer)?.M32;
|
||||||
|
if (position.HasValue)
|
||||||
|
{
|
||||||
|
positions.Add((anchorId, position.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
positions.Sort((a, b) => a.Item2.CompareTo(b.Item2));
|
||||||
|
_positions = positions;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnLoaded(RoutedEventArgs e)
|
protected override void OnLoaded(RoutedEventArgs e)
|
||||||
@@ -122,12 +134,22 @@ public class Anchor: ItemsControl
|
|||||||
var tops = targetItems.Select(a => (a.TransformToVisual(target)?.M32, GetAnchorId(a)));
|
var tops = targetItems.Select(a => (a.TransformToVisual(target)?.M32, GetAnchorId(a)));
|
||||||
var isloaded = TargetContainer?.IsLoaded;
|
var isloaded = TargetContainer?.IsLoaded;
|
||||||
TargetContainer?.AddHandler(ScrollViewer.ScrollChangedEvent, OnScrollChanged);
|
TargetContainer?.AddHandler(ScrollViewer.ScrollChangedEvent, OnScrollChanged);
|
||||||
|
if (isloaded is true)
|
||||||
|
{
|
||||||
|
InvalidateAnchorPositions();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TargetContainer.Loaded += (s, args) => InvalidateAnchorPositions();
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkSelectedContainerByPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnScrollChanged(object? sender, ScrollChangedEventArgs e)
|
private void OnScrollChanged(object? sender, ScrollChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (_scrollingFromSelection) return;
|
if (_scrollingFromSelection) return;
|
||||||
Debug.WriteLine("Scroll changed");
|
MarkSelectedContainerByPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||||
@@ -135,12 +157,7 @@ public class Anchor: ItemsControl
|
|||||||
base.OnPointerPressed(e);
|
base.OnPointerPressed(e);
|
||||||
var source = (e.Source as Visual).GetContainerFromEventSource<AnchorItem>();
|
var source = (e.Source as Visual).GetContainerFromEventSource<AnchorItem>();
|
||||||
if (source is null) return;
|
if (source is null) return;
|
||||||
if (_selectedContainer is not null)
|
MarkSelectedContainer(source);
|
||||||
{
|
|
||||||
_selectedContainer.IsSelected = false;
|
|
||||||
}
|
|
||||||
source.IsSelected = true;
|
|
||||||
_selectedContainer = source;
|
|
||||||
var target = TargetContainer?.GetVisualDescendants()
|
var target = TargetContainer?.GetVisualDescendants()
|
||||||
.FirstOrDefault(a => Anchor.GetAnchorId(a) == source?.AnchorId);
|
.FirstOrDefault(a => Anchor.GetAnchorId(a) == source?.AnchorId);
|
||||||
if (target is null) return;
|
if (target is null) return;
|
||||||
@@ -172,5 +189,26 @@ public class Anchor: ItemsControl
|
|||||||
|
|
||||||
internal AnchorItem? _selectedContainer;
|
internal AnchorItem? _selectedContainer;
|
||||||
|
|
||||||
|
internal void MarkSelectedContainer(AnchorItem? item)
|
||||||
|
{
|
||||||
|
var oldValue = _selectedContainer;
|
||||||
|
var newValue = item;
|
||||||
|
if (oldValue == newValue) return;
|
||||||
|
_selectedContainer?.SetValue(AnchorItem.IsSelectedProperty, false);
|
||||||
|
_selectedContainer = newValue;
|
||||||
|
_selectedContainer?.SetValue(AnchorItem.IsSelectedProperty, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void MarkSelectedContainerByPosition()
|
||||||
|
{
|
||||||
|
if (TargetContainer is null) return;
|
||||||
|
var top = TargetContainer.Offset.Y;
|
||||||
|
var topAnchorId = _positions.LastOrDefault(a => a.Item2 <= top).Item1;
|
||||||
|
if (topAnchorId is null) return;
|
||||||
|
var item = this.GetVisualDescendants().OfType<AnchorItem>()
|
||||||
|
.FirstOrDefault(a => a.AnchorId == topAnchorId);
|
||||||
|
if (item is null) return;
|
||||||
|
MarkSelectedContainer(item);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -55,21 +55,6 @@ public class AnchorItem : HeaderedItemsControl, ISelectable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
|
||||||
{
|
|
||||||
// var item = new TreeViewItem();
|
|
||||||
base.OnPointerPressed(e);
|
|
||||||
return;
|
|
||||||
if (e.Handled) return;
|
|
||||||
if (_root is null)
|
|
||||||
return;
|
|
||||||
if (!string.IsNullOrEmpty(AnchorId))
|
|
||||||
{
|
|
||||||
_root.ScrollToAnchor(AnchorId);
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
||||||
{
|
{
|
||||||
return EnsureRoot().CreateContainerForItemOverride_INTERNAL(item, index, recycleKey);
|
return EnsureRoot().CreateContainerForItemOverride_INTERNAL(item, index, recycleKey);
|
||||||
|
|||||||
Reference in New Issue
Block a user