【问题标题】:Binding to a ScrollViewer's ViewportWidth and ViewportHeight绑定到 ScrollViewer 的 ViewportWidth 和 ViewportHeight
【发布时间】:2011-03-17 01:41:02
【问题描述】:

我在我正在构建的 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)。

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

【问题讨论】:

    标签: c# wpf height width scrollviewer


    【解决方案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;
                }
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      您可以尝试运行一些更新视图模型的 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;
      }
      

      【讨论】:

        猜你喜欢
        • 2018-07-10
        • 1970-01-01
        • 1970-01-01
        • 2019-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多