【问题标题】:Capture mouse clicks on WPF scrollbar of a TextBox在 TextBox 的 WPF 滚动条上捕获鼠标点击
【发布时间】:2014-08-19 22:25:09
【问题描述】:

我有一个 WPF ScrollingTextBox 定义如下。 此文本框是只读的,每当触发来自 ViewModel 的事件时,其内容都会更新。

<Grid>
    <StackPanel>
        <local:ScrollingTextBox x:Name="textBox1"
                                Width="480"
                                Height="100"
                                Margin="12,12,0,0"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Top"
                                IsReadOnly="True"
                                Background="Black"
                                Foreground="White"
                 Text="{Binding Path=UpdatedText, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"/>
    </StackPanel>
</Grid>

我必须定义以下类,以便在将新文本添加到文本框时启用自动向下滚动。此外,我需要重写OnPreviewMouseLeftButtonDownOnPreviewMouseLeftButtonUp 方法,以便在用户单击滚动条时禁用自动向下滚动:这些方法和FindVisualParent 方法中包含的指令来自this page .

public class ScrollingTextBox : TextBox
{
    private volatile bool _AutomaticScrollingEnabled = true;

    protected override void OnInitialized(EventArgs e)
    {
        base.OnInitialized(e);

        VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
        HorizontalScrollBarVisibility = ScrollBarVisibility.Visible;
    }

    protected override void OnTextChanged(TextChangedEventArgs e)
    {
        base.OnTextChanged(e);

        if (_AutomaticScrollingEnabled)
        {
            Focus();
            CaretIndex = Text.Length;
            ScrollToEnd();
        }
    }

    protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        base.OnPreviewMouseLeftButtonDown(e);
        object original = e.OriginalSource;

        if (!original.GetType().Equals(typeof(ScrollViewer)))
        {
            if (FindVisualParent<ScrollBar>(original as DependencyObject) != null)
            {
                _AutomaticScrollingEnabled = false;
                Trace.WriteLine("scroll bar is clicked down");
            }
        }
    }

    protected override void OnPreviewMouseLeftButtonUp(MouseButtonEventArgs e)
    {
        base.OnPreviewMouseLeftButtonUp(e);
        object original = e.OriginalSource;

        if (!original.GetType().Equals(typeof(ScrollViewer)))
        {
            if (FindVisualParent<ScrollBar>(original as DependencyObject) != null)
            {
                _AutomaticScrollingEnabled = true;
                Trace.WriteLine("scroll bar is clicked up");
            }
        }
    }

    private parentItem FindVisualParent<parentItem>(DependencyObject obj) where parentItem : DependencyObject
    {
        DependencyObject parent = VisualTreeHelper.GetParent(obj);
        while (parent != null && !parent.GetType().Equals(typeof(parentItem)))
        {
            parent = VisualTreeHelper.GetParent(parent);
        }
        return parent as parentItem;
    }

}
  1. 为什么我需要验证事件原始来源不等于typeof(ScrollViewer)
  2. FindVisualParent 方法是如何工作的?

【问题讨论】:

  • 我有点困惑......你写了这门课,但你问它是如何工作的?
  • @McGarnagle:我在阅读this page 后编写了方法FindVisualParent,我想了解它是如何工作的......

标签: c# .net wpf events


【解决方案1】:

为什么我需要验证事件原始来源是否不等于typeof(ScrollViewer)?

我认为关键是要确定用户点击ScrollViewer 的确切位置。因此,如果 ScrollViewer 本身正在发送事件,那是没有用的,并且您想等到事件向下传输到您感兴趣的特定子节点之一。(请注意,PreviewMouseLeftButtonUpPreviewMouseLeftButtonDown 是隧道事件,这意味着事件从根向下通过可视化树进行,直到它们被处理。)

FindVisualParent 方法是如何工作的?

它只是爬上可视化树,直到找到指定类型的元素(“parentItem”)或到达顶部。

private parentItem FindVisualParent<parentItem>(DependencyObject obj) 
    where parentItem : DependencyObject
{
    // start by getting the parent of the input element
    DependencyObject parent = VisualTreeHelper.GetParent(obj);

    // repeat until there is no parent, or the current element matches the target type
    while (parent != null && !parent.GetType().Equals(typeof(parentItem)))
    {
        // get the next element up
        parent = VisualTreeHelper.GetParent(parent);
    }

    // return the found element of type "parentItem", or null if not found
    return parent as parentItem;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 2015-06-15
    • 1970-01-01
    相关资源
    最近更新 更多