enter code here
每当我从后面的代码调用ScrollToVerticalOffset方法时,Silverlight中的ScrollViewer都不会垂直滚动。
基本上,我的View(UserControl)包含ScrollViewer。我从我的ViewModel调用一个动作,该动作触发View的代码隐藏中的事件,该事件将VerticalOffset设置为特定值。
首先,我知道这非常难看。理想情况下,我希望我可以有一个可附加的属性,我可以绑定到我的ViewModel中的属性,当设置时,将导致VerticalOffset属性(我知道是只读的)更新,并滚动ScrollViewer。
ScrollViewer包含动态内容。因此,如果用户正在ScrollViewer中查看内容,并向下滚动一半,然后单击一个按钮,则新内容将加载到ScrollViewer中。问题是ScrollViewer的垂直偏移不会被重置,因此用户必须向上滚动才能读取内容。所以,我的解决方案是能够控制ViewModel的垂直偏移,我已经绞尽脑汁,无法找到可行的解决方案,所以我正在找人帮忙。
顺便说一句 - 我已经将我编写的类中的代码包含在一个可附加属性中。此属性绑定到ViewModel中的属性。当我在ViewModel中设置属性时,它会正确触发此类中的PropertyChanged回调方法,该方法然后调用ScrollViewer的ScrollToVerticalOffset方法,但ScrollViewer仍然不会滚动。
public class ScrollViewerHelper
{
public static readonly DependencyProperty BindableOffsetProperty =
DependencyProperty.RegisterAttached("BindableOffset", typeof(double), typeof(ScrollViewerHelper),
new PropertyMetadata(OnBindableOffsetChanged));
public static double GetBindableOffset(DependencyObject d)
{
return (double)d.GetValue(BindableOffsetProperty);
}
public static void SetBindableOffset(DependencyObject d, double value)
{
d.SetValue(BindableOffsetProperty, value);
}
private static void OnBindableOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ScrollViewer scrollViewer = d as ScrollViewer;
if (scrollViewer != null)
{
scrollViewer.ScrollToVerticalOffset((double)e.NewValue);
}
}
}
答案 0 :(得分:0)
在我看来,这种方法有点时髦,因为我认为ScrollViewer和VerticalScrollOffset都是“View”实体,它们与ViewModel的关系应该很少(或没有)。看起来这可能会迫使MVVM有点过多,并且在创建附加依赖项属性时创建了大量额外工作,并且基本上试图使绑定的Offset ViewModel属性与ScrollViewer的只读VerticalScrollOffset保持同步。
我并非确切地确定您要实现的目标,但听起来当您将某个动态元素添加到ScrollViewer的基础面板时,您正在尝试滚动到指定的偏移量。就个人而言,我只想在我的视图中使用一些代码来处理这种行为,而忘记将它绑定到ViewModel。
在Silverlight 3中执行此类操作的一个非常好的方法是使用Blend行为。您在C#中编写了一些行为代码,然后可以声明性地将其附加到XAML中的元素。这使它可以重复使用,而不是代码隐藏。您的项目必须引用System.Windows.Interactivity DLL,它是Blend SKD的一部分。
这是一个简单的Blend行为的简单示例,您可以添加到ScrollViewer,只要ScrollViewer的基础内容的大小发生变化,它就会滚动到指定的偏移量:
public class ScrollToOffsetBehavior : Behavior<ScrollViewer>
{
private FrameworkElement contentElement = null;
public static readonly DependencyProperty OffsetProperty = DependencyProperty.Register(
"Offset",
typeof(double),
typeof(ScrollToOffsetBehavior),
new PropertyMetadata(0.0));
public double Offset
{
get { return (double)GetValue(OffsetProperty); }
set { SetValue(OffsetProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
if (this.AssociatedObject != null)
{
this.AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded);
}
}
protected override void OnDetaching()
{
base.OnDetaching();
if (this.contentElement != null)
{
this.contentElement.SizeChanged -= contentElement_SizeChanged;
}
if (this.AssociatedObject != null)
{
this.AssociatedObject.Loaded -= AssociatedObject_Loaded;
}
}
void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
this.contentElement = this.AssociatedObject.Content as FrameworkElement;
if (this.contentElement != null)
{
this.contentElement.SizeChanged += new SizeChangedEventHandler(contentElement_SizeChanged);
}
}
void contentElement_SizeChanged(object sender, SizeChangedEventArgs e)
{
this.AssociatedObject.ScrollToVerticalOffset(this.Offset);
}
}
然后,您可以将此行为应用于XAML中的ScrollViewer(并指定偏移量0以滚动回顶部):
<ScrollViewer>
<i:Interaction.Behaviors>
<local:ScrollToOffsetBehavior Offset="0"/>
</i:Interaction.Behaviors>
...Scroll Viewer Content...
</ScrollViewer>
这将假设您始终希望在内容大小更改时滚动到偏移量。这可能不是您正在寻找的,但它是使用行为在视图中完成此类事情的一个示例。