Wpf 如何链接滚动条和滚动查看器
我目前有两个ScrollViewer,其中包含同一集合的备选视图。我通过处理ScrollChanged事件并使用ScrollToVerticalOffset将两个ScrollViewer的滚动绑定在一起 出于演示的原因,我将两个ScrollViewer滚动条都设置为隐藏,并希望通过一个单独的滚动条来控制它们 这似乎并不简单。我记得几个月前看过一篇关于它的博客,但我再也找不到了 谁能给我指出一些有用的资源的方向,或者给我一个正确的方向,告诉我如何实现它Wpf 如何链接滚动条和滚动查看器,wpf,scrollbar,scrollviewer,Wpf,Scrollbar,Scrollviewer,我目前有两个ScrollViewer,其中包含同一集合的备选视图。我通过处理ScrollChanged事件并使用ScrollToVerticalOffset将两个ScrollViewer的滚动绑定在一起 出于演示的原因,我将两个ScrollViewer滚动条都设置为隐藏,并希望通过一个单独的滚动条来控制它们 这似乎并不简单。我记得几个月前看过一篇关于它的博客,但我再也找不到了 谁能给我指出一些有用的资源的方向,或者给我一个正确的方向,告诉我如何实现它 提前谢谢。好的,解决了这个问题。其实很简单
提前谢谢。好的,解决了这个问题。其实很简单 已经找到了,这应该会帮助其他感兴趣的人。它是VB,但应该足够清晰 干杯 更进一步:我对ScrollBar进行了子类化,并传入了我想要绑定的ScrollViewer。 看起来不错
public class ScrollViewerBoundScrollBar : ScrollBar
{
private ScrollViewer _scrollViewer;
public ScrollViewer BoundScrollViewer { get { return _scrollViewer; } set { _scrollViewer = value; UpdateBindings(); } }
public ScrollViewerBoundScrollBar( ScrollViewer scrollViewer, Orientation o ) : base()
{
this.Orientation = o;
BoundScrollViewer = _scrollViewer;
}
public ScrollViewerBoundScrollBar() : base()
{
}
private void UpdateBindings()
{
this.AddHandler(ScrollBar.ScrollEvent, new ScrollEventHandler(OnScroll));
_scrollViewer.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(BoundScrollChanged));
this.Minimum = 0;
if (Orientation == Orientation.Horizontal)
{
this.SetBinding(ScrollBar.MaximumProperty, (new Binding("ScrollableWidth") { Source = _scrollViewer, Mode = BindingMode.OneWay }));
this.SetBinding(ScrollBar.ViewportSizeProperty, (new Binding("ViewportWidth") { Source = _scrollViewer, Mode = BindingMode.OneWay }));
}
else
{
this.SetBinding(ScrollBar.MaximumProperty, (new Binding("ScrollableHeight") { Source = _scrollViewer, Mode = BindingMode.OneWay }));
this.SetBinding(ScrollBar.ViewportSizeProperty, (new Binding("ViewportHeight") { Source = _scrollViewer, Mode = BindingMode.OneWay }));
}
this.LargeChange = 242;
this.SmallChange = 16;
}
public void BoundScrollChanged(object sender, ScrollChangedEventArgs e)
{
switch (this.Orientation)
{
case Orientation.Horizontal:
this.Value = e.HorizontalOffset;
break;
case Orientation.Vertical:
this.Value = e.VerticalOffset;
break;
default:
break;
}
}
public void OnScroll(object sender, ScrollEventArgs e)
{
switch(this.Orientation)
{
case Orientation.Horizontal:
this.BoundScrollViewer.ScrollToHorizontalOffset(e.NewValue);
break;
case Orientation.Vertical:
this.BoundScrollViewer.ScrollToVerticalOffset(e.NewValue);
break;
default:
break;
}
}
}
太好了,正是我需要的。我对scrollviewer进行了一些扩展,这样就可以使用依赖属性从xaml设置scrollviewer。在xaml中:
<local:BindableScrollBar BoundScrollViewer ="{Binding ElementName=ScrollViewer}" Orientation="Vertical" />
代码:
//
///可绑定到外部scrollviewer的扩展滚动条。
///
公共类BindableScrollBar:ScrollBar
{
公共滚动查看器BoundScrollViewer
{
获取{return(ScrollViewer)GetValue(BoundScrollViewerProperty);}
设置{SetValue(BoundScrollViewerProperty,value);}
}
//使用DependencyProperty作为BoundScrollViewer的备份存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性BoundScrollViewerProperty=
DependencyProperty.Register(“BoundScrollViewer”、typeof(ScrollViewer)、typeof(BindableCrollbar)、new FrameworkPropertyMetadata(null、new PropertyChangedCallback(OnBoundScrollViewerPropertyChanged));
私有静态无效OnBoundScrollViewerPropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
BindableScrollBar sender=d作为BindableScrollBar;
if(发送方!=null&&e.NewValue!=null)
{
sender.UpdateBindings();
}
}
///
///初始化类的新实例。
///
///滚动查看器。
///o。
公共BindableCrollbar(ScrollViewer ScrollViewer,方向o)
:base()
{
这个方向=o;
BoundScrollViewer=滚动查看器;
}
///
///初始化类的新实例。
///
public BindableScrollBar():base(){}
私有void UpdateBindings()
{
AddHandler(ScrollBar.ScrollEvent,新的ScrollEventHandler(OnScroll));
BoundScrollViewer.AddHandler(ScrollViewer.ScrollChangedEvent,新的ScrollChangedEventHandler(BoundScrollChanged));
最小值=0;
如果(方向==方向.水平)
{
设置绑定(ScrollBar.MaximumProperty,(新绑定(“ScrollableWidth”){Source=BoundScrollViewer,Mode=BindingMode.OneWay});
SetBinding(ScrollBar.ViewportSizeProperty,(新绑定(“ViewportWidth”){Source=BoundScrollViewer,Mode=BindingMode.OneWay});
}
其他的
{
SetBinding(ScrollBar.MaximumProperty,(新绑定(“ScrollableHeight”){Source=BoundScrollViewer,Mode=BindingMode.OneWay});
SetBinding(ScrollBar.ViewportSizeProperty,(新绑定(“ViewportHeight”){Source=BoundScrollViewer,Mode=BindingMode.OneWay});
}
大变化=242;
微小变化=16;
}
私有void BoundScrollChanged(对象发送方,ScrollChangedEventArgs e)
{
开关(此方向)
{
案例方向。横向:
该值=e.水平偏移量;
打破
案例方向。垂直:
此.值=e.垂直偏移;
打破
违约:
打破
}
}
私有void OnScroll(对象发送方,ScrollEventArgs e)
{
开关(此方向)
{
案例方向。横向:
这个.BoundScrollViewer.ScrollToHorizontalOffset(e.NewValue);
打破
案例方向。垂直:
这个.BoundScrollViewer.ScrollToVerticalOffset(e.NewValue);
打破
违约:
打破
}
}
}
应用模板后,如何将bindablescrollbar绑定到模板项?创建可绑定滚动条时,我的另一个scrollviewer还不存在,因此该项没有绑定。设置LargeChange=0.1*最大值是否更好代码>和SmallChange=0.02*最大值
而不是使用硬编码值?@JamesJoshuaStreet您可以订阅某些事件,然后取消订阅。例如,在我的例子中,我尝试绑定到一个DataGrid
,其中ScrollViewer
在绑定时不存在。在OnBoundDataGridPropertyChanged
中,我绑定到Loaded
事件:((DataGrid)e.NewValue)。Loaded+=sender.OnBoundTableLoaded代码>。然后,在OnBoundTableLoaded
中,我从它取消订阅OnBoundTableLoaded
。
/// <summary>
/// An extended scrollbar that can be bound to an external scrollviewer.
/// </summary>
public class BindableScrollBar : ScrollBar
{
public ScrollViewer BoundScrollViewer
{
get { return (ScrollViewer)GetValue(BoundScrollViewerProperty); }
set { SetValue(BoundScrollViewerProperty, value); }
}
// Using a DependencyProperty as the backing store for BoundScrollViewer. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BoundScrollViewerProperty =
DependencyProperty.Register("BoundScrollViewer", typeof(ScrollViewer), typeof(BindableScrollBar), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnBoundScrollViewerPropertyChanged)));
private static void OnBoundScrollViewerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
BindableScrollBar sender = d as BindableScrollBar;
if (sender != null && e.NewValue != null)
{
sender.UpdateBindings();
}
}
/// <summary>
/// Initializes a new instance of the <see cref="BindableScrollBar"/> class.
/// </summary>
/// <param name="scrollViewer">The scroll viewer.</param>
/// <param name="o">The o.</param>
public BindableScrollBar(ScrollViewer scrollViewer, Orientation o)
: base()
{
this.Orientation = o;
BoundScrollViewer = scrollViewer;
}
/// <summary>
/// Initializes a new instance of the <see cref="BindableScrollBar"/> class.
/// </summary>
public BindableScrollBar() : base() { }
private void UpdateBindings()
{
AddHandler(ScrollBar.ScrollEvent, new ScrollEventHandler(OnScroll));
BoundScrollViewer.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(BoundScrollChanged));
Minimum = 0;
if (Orientation == Orientation.Horizontal)
{
SetBinding(ScrollBar.MaximumProperty, (new Binding("ScrollableWidth") { Source = BoundScrollViewer, Mode = BindingMode.OneWay }));
SetBinding(ScrollBar.ViewportSizeProperty, (new Binding("ViewportWidth") { Source = BoundScrollViewer, Mode = BindingMode.OneWay }));
}
else
{
this.SetBinding(ScrollBar.MaximumProperty, (new Binding("ScrollableHeight") { Source = BoundScrollViewer, Mode = BindingMode.OneWay }));
this.SetBinding(ScrollBar.ViewportSizeProperty, (new Binding("ViewportHeight") { Source = BoundScrollViewer, Mode = BindingMode.OneWay }));
}
LargeChange = 242;
SmallChange = 16;
}
private void BoundScrollChanged(object sender, ScrollChangedEventArgs e)
{
switch (this.Orientation)
{
case Orientation.Horizontal:
this.Value = e.HorizontalOffset;
break;
case Orientation.Vertical:
this.Value = e.VerticalOffset;
break;
default:
break;
}
}
private void OnScroll(object sender, ScrollEventArgs e)
{
switch (this.Orientation)
{
case Orientation.Horizontal:
this.BoundScrollViewer.ScrollToHorizontalOffset(e.NewValue);
break;
case Orientation.Vertical:
this.BoundScrollViewer.ScrollToVerticalOffset(e.NewValue);
break;
default:
break;
}
}
}