【问题标题】:Get the scroll position of a WPF TextBox获取 WPF 文本框的滚动位置
【发布时间】:2013-02-15 19:58:32
【问题描述】:

我需要为 WPF TextBox 控件的内容添加一些装饰。这基本上可以正常工作,我可以获得指定字符索引的位置并相应地布局我的其他元素。但是当滚动 TextBox 时,这一切都会中断。我的布局位置不再与显示的文本匹配,因为它已移动到其他地方。

现在我很惊讶 TextBox 类没有提供有关其滚动状态的任何信息,也没有提供滚动更改时的任何事件。我现在能做什么?

我使用 Snoop 来确定是否有一些我可以询问的滚动子元素,但 ScrollContentPresenter 也没有任何可用的滚动信息。我真的很想将我的装饰元素直接放入滚动区域,以便滚动也能影响它们,但只能有一个内容控件,这已经是 TextBox 内部结构之一了。

【问题讨论】:

  • 也许尝试订阅 ScrollViewer.ScrollChanged 路由事件?它提供了诸如范围高度、滚动偏移、视口大小(均以水平和垂直尺寸表示)之类的信息,也许它会有所帮助。我不太确定我完全理解你的任务。不过试试看吧。

标签: wpf textbox scroll


【解决方案1】:

我不确定在滚动文本框时如何捕获事件(可能使用 narohi 的答案),但有一种简单的方法可以查看当前滚动位置是什么:

// Gets or sets the vertical scroll position.
textBox.VerticalOffset

(来自http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.textboxbase.verticaloffset(v=vs.100).aspx

我用它来查看文本框是否滚动到最后,像这样:

public static bool IsScrolledToEnd(this TextBox textBox)
{
    return textBox.VerticalOffset + textBox.ViewportHeight == textBox.ExtentHeight;
}

【讨论】:

  • 约翰,谢谢,我试过你的 IsScrolledToEnd。它通常有效,但并非总是如此。问题是您正在使用 == 运算符比较双打。我认为在这个比较中应该有 1 行容差,像这样:bool scrollToEnd = Memo.VerticalOffset > Memo.ExtentHeight - Memo.ViewportHeight - fontHeight;
  • @Aleksandr 你从哪里得到“fontHeight”?我使用了“Memo.FontSize”,它似乎按预期工作。
  • double fontHeight = Memo.FontSize * Memo.FontFamily.LineSpacing;
【解决方案2】:

您可以使用此方法获取 ScrollViewer,方法是将您的文本框作为参数和 ScrollView 类型传入。然后你可以订阅 ScrollChanged 事件。

public static T FindDescendant<T>(DependencyObject obj) where T : DependencyObject
{
    if (obj == null) return default(T);
    int numberChildren = VisualTreeHelper.GetChildrenCount(obj);
    if (numberChildren == 0) return default(T);

    for (int i = 0; i < numberChildren; i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if (child is T)
        {
            return (T)(object)child;
        }
    }

    for (int i = 0; i < numberChildren; i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        var potentialMatch = FindDescendant<T>(child);
        if (potentialMatch != default(T))
        {
            return potentialMatch;
        }
    }

    return default(T);
}

例子:

public MainWindow()
{
    InitializeComponent();
    Loaded += new RoutedEventHandler(MainWindow_Loaded);
}

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    ScrollViewer s = FindDescendant<ScrollViewer>(txtYourTextBox);
    s.ScrollChanged += new ScrollChangedEventHandler(s_ScrollChanged);
}

void s_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
    // check event args for information needed
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    • 2011-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多