【问题标题】:Silverlight ScrollViewer Not ScrollingSilverlight ScrollViewer 不滚动
【发布时间】:2010-01-26 22:34:36
【问题描述】:

enter code here我在 Silverlight 中有一个 ScrollViewer,当我从后面的代码调用 ScrollToVerticalOffset 方法时,它不会垂直滚动。

基本上,我的视图 (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);
        }
    }
}

【问题讨论】:

  • 我不明白为什么这个解决方案不起作用...您只是想在添加新内容时将视口固定到元素面板的顶部或底部?您确定每次添加新元素时都会调用 OnBindableOffsetChanged 吗?如果您只是每次都将视图模型属性设置为 0.0(滚动到顶部),我可以理解为什么它可能只会在第一次被调用而不再被调用。

标签: c# silverlight


【解决方案1】:

在我看来,这种方法有点古怪,因为我认为 ScrollViewer 和 VerticalScrollOffset 都是“视图”实体,它们应该与 ViewModel 几乎没有关系(或没有关系)。看起来这可能会强制 MVVM 有点过分,并在创建附加依赖项属性和基本上尝试保持绑定的 Offset ViewModel 属性与 ScrollViewer 的只读 VerticalScrollOffset 同步方面创建大量额外工作。

我不确定确切您要达到的目标,但当某些动态元素添加到 ScrollViewer 的底层面板时,听起来您正在尝试滚动到指定的偏移量。就个人而言,我只想在我的视图中使用一点代码来处理这种行为,而忘记将其绑定到视图模型。

在 Silverlight 3 中执行此类操作的一个非常好的方法是使用混合行为。您在 C# 中编写了一些行为代码,然后可以以声明方式将其附加到 XAML 中的元素。这使它可重用并且不受您的代码隐藏。您的项目必须引用作为 Blend SKD 一部分的 System.Windows.Interactivity DLL。

这是一个简单的 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>

这假设您总是希望在内容大小发生变化时滚动到偏移量。这可能不是您正在寻找的内容,但它是如何使用行为在视图中完成此类操作的一个示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 2017-01-02
    相关资源
    最近更新 更多