我正在构建的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所以在这个绑定中。
任何人都知道能够做这样的事情的好方法吗?
答案 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的完整代码隐藏。请注意,我有四个可绑定的依赖项属性,名为DynamicHorizontalOffset,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;
}
}
}
}