Skip to content

Instantly share code, notes, and snippets.

@rootasjey
Created October 9, 2016 19:58
Show Gist options
  • Save rootasjey/f0f9b28a1c2eded5a7c9da9f209db3e5 to your computer and use it in GitHub Desktop.
Save rootasjey/f0f9b28a1c2eded5a7c9da9f209db3e5 to your computer and use it in GitHub Desktop.
Retrieve XAML control from code behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media;
namespace appNamespace.Helpers {
public static class VisualTreeExtensions {
public static T GetChildOfType<T>(this DependencyObject depObj) where T : DependencyObject {
if (depObj == null) return null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) {
var child = VisualTreeHelper.GetChild(depObj, i);
var result = (child as T) ?? GetChildOfType<T>(child);
if (result != null) return result;
}
return null;
}
public static T GetParentOfType<T>(this DependencyObject depObj) where T : DependencyObject {
if (depObj == null) return null;
var parent = VisualTreeHelper.GetParent(depObj);
var result = (parent as T) ?? GetParentOfType<T>(parent);
if (result != null) return result;
return null;
}
public async static Task ScrollToIndex(this ListViewBase listViewBase, int index) {
bool isVirtualizing = default(bool);
double previousHorizontalOffset = default(double), previousVerticalOffset = default(double);
// get the ScrollViewer withtin the ListView/GridView
//var scrollViewer = listViewBase.GetScrollViewer();
var scrollViewer = listViewBase.GetChildOfType<ScrollViewer>();
// get the SelectorItem to scroll to
var selectorItem = listViewBase.ContainerFromIndex(index) as SelectorItem;
// when it's null, means virtualization is on and the item hasn't been realized yet
if (selectorItem == null) {
isVirtualizing = true;
previousHorizontalOffset = scrollViewer.HorizontalOffset;
previousVerticalOffset = scrollViewer.VerticalOffset;
// call task-based ScrollIntoViewAsync to realize the item
await listViewBase.ScrollIntoViewAsync(listViewBase.Items[index]);
// this time the item shouldn't be null again
selectorItem = (SelectorItem)listViewBase.ContainerFromIndex(index);
}
// calculate the position object in order to know how much to scroll to
var transform = selectorItem.TransformToVisual((UIElement)scrollViewer.Content);
var position = transform.TransformPoint(new Point(0, 0));
// when virtualized, scroll back to previous position without animation
if (isVirtualizing) {
await scrollViewer.ChangeViewAsync(previousHorizontalOffset, previousVerticalOffset, true);
}
// scroll to desired position with animation!
scrollViewer.ChangeView(position.X, position.Y, null);
}
public async static Task ScrollToItem(this ListViewBase listViewBase, object item) {
bool isVirtualizing = default(bool);
double previousHorizontalOffset = default(double), previousVerticalOffset = default(double);
// get the ScrollViewer withtin the ListView/GridView
//var scrollViewer = listViewBase.GetScrollViewer();
var scrollViewer = listViewBase.GetChildOfType<ScrollViewer>();
// get the SelectorItem to scroll to
var selectorItem = listViewBase.ContainerFromItem(item) as SelectorItem;
// when it's null, means virtualization is on and the item hasn't been realized yet
if (selectorItem == null) {
isVirtualizing = true;
previousHorizontalOffset = scrollViewer.HorizontalOffset;
previousVerticalOffset = scrollViewer.VerticalOffset;
// call task-based ScrollIntoViewAsync to realize the item
await listViewBase.ScrollIntoViewAsync(item);
// this time the item shouldn't be null again
selectorItem = (SelectorItem)listViewBase.ContainerFromItem(item);
}
// calculate the position object in order to know how much to scroll to
var transform = selectorItem.TransformToVisual((UIElement)scrollViewer.Content);
var position = transform.TransformPoint(new Point(0, 0));
// when virtualized, scroll back to previous position without animation
if (isVirtualizing) {
await scrollViewer.ChangeViewAsync(previousHorizontalOffset, previousVerticalOffset, true);
}
// scroll to desired position with animation!
scrollViewer.ChangeView(position.X, position.Y, null);
}
public static async Task ScrollIntoViewAsync(this ListViewBase listViewBase, object item) {
var tcs = new TaskCompletionSource<object>();
//var scrollViewer = listViewBase.GetScrollViewer();
var scrollViewer = listViewBase.GetChildOfType<ScrollViewer>();
EventHandler<ScrollViewerViewChangedEventArgs> viewChanged = (s, e) => tcs.TrySetResult(null);
try {
scrollViewer.ViewChanged += viewChanged;
listViewBase.ScrollIntoView(item, ScrollIntoViewAlignment.Leading);
await tcs.Task;
}
finally {
scrollViewer.ViewChanged -= viewChanged;
}
}
public static async Task ChangeViewAsync(this ScrollViewer scrollViewer, double? horizontalOffset, double? verticalOffset, bool disableAnimation) {
var tcs = new TaskCompletionSource<object>();
EventHandler<ScrollViewerViewChangedEventArgs> viewChanged = (s, e) => tcs.TrySetResult(null);
try {
scrollViewer.ViewChanged += viewChanged;
scrollViewer.ChangeView(horizontalOffset, verticalOffset, null, disableAnimation);
await tcs.Task;
}
finally {
scrollViewer.ViewChanged -= viewChanged;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment