.net中同步多个ScrollViewer滚动的四种方法
在.net中,Wpf是有ScrollChanged事件的,而silverilght(pc/wp7)则没有,提供以下几种方案:
第一种:(简易,推荐,尤其SL)
private void Test_Loaded(object sender, RoutedEventArgs e)
{
sv1 = VisualTreeHelper.GetChild(this.Listbox1, 0) as ScrollViewer;
sv2 = VisualTreeHelper.GetChild(this.Listbox2, 0) as ScrollViewer;
var binding = new Binding("VerticalOffset") { Source = sv1 };
var offsetChangeListener = DependencyProperty.RegisterAttached("ListenerOffset",
typeof(object), typeof(UserControl), new PropertyMetadata(OnScrollChanged));
sv1.SetBinding(offsetChangeListener, binding);
binding = new Binding("VerticalOffset") { Source = sv2 };
offsetChangeListener = DependencyProperty.RegisterAttached("ListenerOffset",
typeof(object), typeof(UserControl), new PropertyMetadata(OnScrollChanged2));
sv2.SetBinding(offsetChangeListener, binding);
}
public void OnScrollChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
double a = (double)e.NewValue;
sv2.ScrollToVerticalOffset(a);
}
public void OnScrollChanged2(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
double a = (double)e.NewValue;
sv1.ScrollToVerticalOffset(a);
}
第二种:(推荐)
ScrollBar bar1, bar2;
ScrollViewer sv1, sv2;
private void EnoTest_Loaded(object sender, RoutedEventArgs e)
{
sv1 = VisualTreeHelper.GetChild(this.enoListbox1, 0) as ScrollViewer;
sv2 = VisualTreeHelper.GetChild(this.enoListbox2, 0) as ScrollViewer;
bar1 = GetScrollBar(sv1, false);
bar2 = GetScrollBar(sv2, false);
//bar1.Scroll += delegate { Debug.WriteLine("bar1 Scroll..."); };//Scroll事件响应不了,原因不详
//bar2.Scroll += delegate { Debug.WriteLine("bar2 Scroll..."); };
bar1.ValueChanged += new RoutedPropertyChangedEventHandler<double>(bar1_ValueChanged);
bar2.ValueChanged += new RoutedPropertyChangedEventHandler<double>(bar2_ValueChanged);
}
private void bar1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
sv2.ScrollToVerticalOffset(e.NewValue);
}
private void bar2_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
sv1.ScrollToVerticalOffset(e.NewValue);
}
private ScrollBar GetScrollBar(ScrollViewer viewer, bool isHor)
{
var a = VisualTreeHelper.GetChild(viewer, 0);
var b = VisualTreeHelper.GetChild(a, 0);
var c = VisualTreeHelper.GetChild(b, 0);
if (isHor)
return VisualTreeHelper.GetChild(b, 2) as ScrollBar;//水平
else
return VisualTreeHelper.GetChild(b, 1) as ScrollBar;//垂直
}
第三种:
public Test()
{
this.Listbox1.ManipulationStarted += new EventHandler<ManipulationStartedEventArgs>(Listbox1_ManipulationStarted);
this.Listbox2.ManipulationStarted += new EventHandler<ManipulationStartedEventArgs>(Listbox2_ManipulationStarted);
this.Loaded += new RoutedEventHandler(Test_Loaded);
timer.Interval = new System.TimeSpan(0, 0, 0, 0, 120);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
}
private void Test_Loaded(object sender, RoutedEventArgs e)
{
sv1 = VisualTreeHelper.GetChild(this.Listbox1, 0) as ScrollViewer;
sv2 = VisualTreeHelper.GetChild(this.Listbox2, 0) as ScrollViewer;
}
private void timer_Tick(object sender, EventArgs e)
{
if (num == 1)
sv2.ScrollToVerticalOffset(sv1.VerticalOffset);
if (num == 2)
sv1.ScrollToVerticalOffset(sv2.VerticalOffset);
}
private void Listbox1_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
num = 1;
}
private void Listbox2_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
num = 2;
}
第四种:(对SL PC&Wp7,wpf均支持)
搜索一下,SynchronizedScrollViewers,提供了wpf/silverlight的一个封装类库,wp7用的话,使用上略有一点不同而已。
第五种:(仅支持wpf,原因是其有事件ScrollChanged)
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
sv1 = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.listbox1, 0), 0) as ScrollViewer;
sv2 = VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.listbox2, 0), 0) as ScrollViewer;
sv1.ScrollChanged += new ScrollChangedEventHandler(sv1_ScrollChanged);
sv2.ScrollChanged += new ScrollChangedEventHandler(sv2_ScrollChanged);
}
void sv1_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
sv2.ScrollToVerticalOffset(sv1.VerticalOffset);
}
void sv2_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
sv1.ScrollToVerticalOffset(sv2.VerticalOffset);
}