Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf 如何链接滚动条和滚动查看器_Wpf_Scrollbar_Scrollviewer - Fatal编程技术网

Wpf 如何链接滚动条和滚动查看器

Wpf 如何链接滚动条和滚动查看器,wpf,scrollbar,scrollviewer,Wpf,Scrollbar,Scrollviewer,我目前有两个ScrollViewer,其中包含同一集合的备选视图。我通过处理ScrollChanged事件并使用ScrollToVerticalOffset将两个ScrollViewer的滚动绑定在一起 出于演示的原因,我将两个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; 
        } 
    }
}