绑定到ScrollViewer的ViewportWidth和ViewportHeight

时间:2010-07-16 16:28:10

标签: c# wpf height width scrollviewer

我正在构建的WPF应用程序中使用Model-View-ViewModel体系结构,我希望特定的ViewModel实际上能够对视图的大小做出反应(不是MVVM方法的正常用例,我知道。)

基本上,我有一个ScrollViewer对象,我希望viewmodel能够观察scrollviewer的宽度和高度,然后根据宽度和高度来做相应的事情。

我想做这样的事情:

<ScrollViewer ViewportWidth="{Binding Path=MyViewportWidth, Mode=OneWayToSource}" ViewportHeight="{Binding Path=MyViewportHeight, Mode=OneWayToSource}" />

但当然这是不可能的,因为“ViewportWidth”和“ViewportHeight”不能“绑定”(也称为绑定目标),因为它们是只读的依赖属性(即使我没有写入它们因为它是OneWayToSource所以在这个绑定中。

任何人都知道能够做这样的事情的好方法吗?

2 个答案:

答案 0 :(得分:1)

您可以尝试运行更新视图模型的OnLoaded或OnResizeChanged

private void ScrollViewer_Loaded(object sender, RoutedEventArgs e)
{
   ScrollViewer sv = sender as ScrollViewer;
   ViewModel vm = sv.DataContext as ViewModel;

   vm.ScrollViewerHeight = sv.ViewportHeight;
   vm.ScrollViewerWidth = sv.ViewportWidth;
}

答案 1 :(得分:1)

好的,这是一个真的旧问题,但我想我会分享后代,因为我自己已经解决了这个问题。我发现的最佳解决方案是创建一个从ScrollView类派生的用户控件,并实现所需的属性 - 这些属性当然与基类的不可绑定属性相关联。

您可以使用OnPropertyChanged函数来监控这些属性并使值保持同步。

这是我的自定义用户控件DynamicScrollViewer的完整代码隐藏。请注意,我有四个可绑定的依赖项属性,名为DynamicHorizo​​ntalOffset,DynamicVerticalOffset,DynamicViewportWidth和DynamicViewportHeight。

两个偏移属性允许对偏移进行读写控制,而视口属性基本上是只读的。

我在创建一个复杂的动画编辑器控件时必须使用这个类,其中各种组件(左边的标签,中间的节点,顶部的时间轴)需要同步滚动,但只是在有限的方面,并且都受到约束常见的外部滚动条。想一想在电子表格中锁定一部分行,你就明白了。

using System.Windows;
using System.Windows.Controls;

namespace CustomControls
{
    public partial class DynamicScrollViewer : ScrollViewer
    {
        public DynamicScrollViewer()
        {
            InitializeComponent();
        }

        public double DynamicHorizontalOffset
        {
            get { return (double)GetValue(DynamicHorizontalOffsetProperty); }
            set { SetValue(DynamicHorizontalOffsetProperty, value); }
        }

        public static readonly DependencyProperty DynamicHorizontalOffsetProperty =
            DependencyProperty.Register("DynamicHorizontalOffset", typeof(double), typeof(DynamicScrollViewer));

        public double DynamicVerticalOffset
        {
            get { return (double)GetValue(DynamicVerticalOffsetProperty); }
            set { SetValue(DynamicVerticalOffsetProperty, value); }
        }

        public static readonly DependencyProperty DynamicVerticalOffsetProperty =
            DependencyProperty.Register("DynamicVerticalOffset", typeof(double), typeof(DynamicScrollViewer));

        public double DynamicViewportWidth
        {
            get { return (double)GetValue(DynamicViewportWidthProperty); }
            set { SetValue(DynamicViewportWidthProperty, value); }
        }

        public static readonly DependencyProperty DynamicViewportWidthProperty =
            DependencyProperty.Register("DynamicViewportWidth", typeof(double), typeof(DynamicScrollViewer));

        public double DynamicViewportHeight
        {
            get { return (double)GetValue(DynamicViewportHeightProperty); }
            set { SetValue(DynamicViewportHeightProperty, value); }
        }

        public static readonly DependencyProperty DynamicViewportHeightProperty =
            DependencyProperty.Register("DynamicViewportHeight", typeof(double), typeof(DynamicScrollViewer));

        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == DynamicVerticalOffsetProperty)
            {
                if (ScrollInfo != null)
                    ScrollInfo.SetVerticalOffset(DynamicVerticalOffset);
            }
            else if (e.Property == DynamicHorizontalOffsetProperty)
            {
                if (ScrollInfo != null)
                    ScrollInfo.SetHorizontalOffset(DynamicHorizontalOffset);
            }
            else if (e.Property == HorizontalOffsetProperty)
            {
                DynamicHorizontalOffset = (double)e.NewValue;
            }
            else if (e.Property == VerticalOffsetProperty)
            {
                DynamicVerticalOffset = (double)e.NewValue;
            }
            else if (e.Property == ViewportWidthProperty)
            {
                DynamicViewportWidth = (double)e.NewValue;
            }
            else if (e.Property == ViewportHeightProperty)
            {
                DynamicViewportHeight = (double)e.NewValue;
            }
        }
    }
}