1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
| public static class ScrollHelper
{
private static Dictionary<string, List<ScrollViewer>> _scrollViewers = new Dictionary<string, List<ScrollViewer>>();
public static string GetScrollGroup(ScrollViewer scrollViewer)
{
return (string)scrollViewer.GetValue(ScrollGroupProperty);
}
public static void SetScrollGroup(ScrollViewer scrollViewer, string value)
{
scrollViewer.SetValue(ScrollGroupProperty, value);
}
// Using a DependencyProperty as the backing store for ScrollGroup. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ScrollGroupProperty =
DependencyProperty.RegisterAttached("ScrollGroup", typeof(string), typeof(ScrollHelper), new PropertyMetadata(null, ScrollGroupChanged));
private static void ScrollGroupChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
ScrollViewer scv = o as ScrollViewer;
if (o != null)
{
string oldGroup = e.OldValue as string;
string newGroup = e.NewValue as string;
if (oldGroup != null)
{
List<ScrollViewer> groupMembers = null;
if (_scrollViewers.TryGetValue(oldGroup, out groupMembers))
{
groupMembers.Remove(scv);
}
DetachScrollEvents(scv);
}
if (newGroup != null)
{
List<ScrollViewer> groupMembers = null;
if (!_scrollViewers.TryGetValue(newGroup, out groupMembers))
{
groupMembers = new List<ScrollViewer>();
_scrollViewers.Add(newGroup, groupMembers);
}
groupMembers.Add(scv);
if (Application.Current.Host.IsLoaded)
{
AttachScrollEvents(scv);
}
else
{
scv.Loaded += new RoutedEventHandler(scv_Loaded);
}
}
}
}
static void scv_Loaded(object sender, RoutedEventArgs e)
{
ScrollViewer scv = sender as ScrollViewer;
if (scv != null)
{
scv.ApplyTemplate();
scv.Loaded -= scv_Loaded;
AttachScrollEvents(scv);
}
}
private static void DetachScrollEvents(ScrollViewer scv)
{
ScrollBar vert = GetScrollBar(scv, "VerticalScrollBar");
ScrollBar horz = GetScrollBar(scv, "HorizontalScrollBar");
if (vert != null)
vert.Scroll -= scv_Scroll;
if (horz != null)
horz.Scroll -= scv_Scroll;
}
private static void AttachScrollEvents(ScrollViewer scv)
{
ScrollBar vert = GetScrollBar(scv, "VerticalScrollBar");
ScrollBar horz = GetScrollBar(scv, "HorizontalScrollBar");
if (vert != null)
vert.Scroll += scv_Scroll;
if (horz != null)
horz.Scroll += scv_Scroll;
}
private static ScrollBar GetScrollBar(ScrollViewer scv, string scrollBarName)
{
var firstChild = VisualTreeHelper.GetChild(scv, 0) as FrameworkElement;
if (firstChild != null)
{
return firstChild.FindName(scrollBarName) as ScrollBar;
}
return null;
}
private static void scv_Scroll(object sender, ScrollEventArgs e)
{
ScrollBar scb = e.OriginalSource as ScrollBar;
ScrollViewer scv = FindParent<ScrollViewer>(scb);
if (scv != null && scb != null)
{
string group = GetScrollGroup(scv);
if (group != null)
{
List<ScrollViewer> groupMembers = null;
if (_scrollViewers.TryGetValue(group, out groupMembers))
{
foreach (var s in groupMembers)
{
if (object.ReferenceEquals(s, scv))
continue;
if (scb.Orientation == Orientation.Horizontal)
{
s.ScrollToHorizontalOffset(e.NewValue);
}
else
{
s.ScrollToVerticalOffset(e.NewValue);
}
}
}
}
}
}
private static T FindParent<T>(DependencyObject o) where T : DependencyObject
{
DependencyObject tmp = o;
while (tmp != null && !(tmp is T))
{
tmp = VisualTreeHelper.GetParent(tmp);
}
return tmp as T;
}
} |
Partager