namespace GummingCommon { using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; public enum SelectiveScrollingOrientation { None, Horizontal, Vertical, Both } public static class ListViewHelper { /// /// Okay, I know this methods cause stack overflow. /// /// /// /// public static T FindAncestor(this DependencyObject element) where T : DependencyObject { if (element == null) { return null; } DependencyObject ancestor = VisualTreeHelper.GetParent(element); if (element is FrameworkElement) { ancestor = ancestor ?? ((element as FrameworkElement).Parent ?? (element as FrameworkElement).TemplatedParent); } return ancestor is T ? ancestor as T : FindAncestor(ancestor); } } public class FixedScrollingGridView : Grid { public static SelectiveScrollingOrientation GetSelectiveScrollingOrientation(DependencyObject obj) { return (SelectiveScrollingOrientation)obj.GetValue(SelectiveScrollingOrientationProperty); } public static void SetSelectiveScrollingOrientation(DependencyObject obj, SelectiveScrollingOrientation value) { obj.SetValue(SelectiveScrollingOrientationProperty, value); } // Using a DependencyProperty as the backing store for SelectiveScrollingOrientation. This enables animation, styling, binding, etc... public static readonly DependencyProperty SelectiveScrollingOrientationProperty = DependencyProperty.RegisterAttached("SelectiveScrollingOrientation", typeof(SelectiveScrollingOrientation), typeof(FixedScrollingGridView), new UIPropertyMetadata(SelectiveScrollingOrientation.Both, new PropertyChangedCallback(OnSelectiveScrollingOrientationChanged))); private static void OnSelectiveScrollingOrientationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement element = d as UIElement; SelectiveScrollingOrientation newValue = (SelectiveScrollingOrientation)e.NewValue; ScrollViewer viewer = element.FindAncestor(); if ((viewer != null) && (element != null)) { Transform renderTransform = element.RenderTransform; if (renderTransform != null) { BindingOperations.ClearBinding(renderTransform, TranslateTransform.XProperty); BindingOperations.ClearBinding(renderTransform, TranslateTransform.YProperty); } if (newValue == SelectiveScrollingOrientation.Both) { element.RenderTransform = null; } else { TranslateTransform target = new TranslateTransform(); if (newValue != SelectiveScrollingOrientation.Horizontal) { Binding binding = new Binding("ContentHorizontalOffset"); binding.Source = viewer; BindingOperations.SetBinding(target, TranslateTransform.XProperty, binding); } if (newValue != SelectiveScrollingOrientation.Vertical) { Binding binding2 = new Binding("ContentVerticalOffset"); binding2.Source = viewer; BindingOperations.SetBinding(target, TranslateTransform.YProperty, binding2); } element.RenderTransform = target; } } } } }