2

我在我正在构建的 WPF 应用程序中使用 Model-View-ViewModel 架构,我希望特定的 ViewModel 实际上对视图的大小有反应(我知道,这不是 MVVM 方法的正常用例) .

本质上,我有一个 ScrollViewer 对象,我希望 viewmodel 观察滚动查看器的宽度和高度,然后能够根据宽度和高度相应地执行操作。

我想做这样的事情:

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

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

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

4

2 回答 2

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;
}
于 2010-07-16T17:03:14.323 回答
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;
            }
        }
    }
}
于 2015-12-08T21:29:32.127 回答