【问题标题】:Hyperlink events are not raised on first click if MousePreviewUp event is subscribed如果订阅了 MousePreviewUp 事件,则在第一次单击时不会引发超链接事件
【发布时间】:2015-11-06 15:45:43
【问题描述】:

我在ContentControl 中加载了一个TextBlock,并在TextBlockInlines 集合中添加了一个Hyperlink 作为对象。

如果我订阅了设置ContentControl.Foreground 属性的ContentControl.PreviewMouseUp 事件的处理程序,则在第一次单击链接时不会引发RequestNavigateClick 事件。如果再次单击该链接,则会引发事件。

如果没有订阅事件,或者处理程序什么都不做,一切正常。


初始化代码(在窗口构造函数中,在InitializeComponent()之后):

var run = new Run("Google");
Hyperlink hyperlink = new Hyperlink(run);
hyperlink.Click += hyperlink_Click;
hyperlink.RequestNavigate += hyper_RequestNavigate;
hyperlink.NavigateUri = new Uri("http://www.google.com");
textBlock.Inlines.Clear();
textBlock.Inlines.Add(hyperlink);

事件处理程序如下:

private void hyper_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
    System.Diagnostics.Process.Start(e.Uri.ToString());
}

void contentControl_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
    contentControl.Foreground = Brushes.Green;
}

void hyperlink_Click(object sender, RoutedEventArgs e)
{

}

XAML如下:

<Grid>
    <ContentControl Name="contentControl">
        <TextBlock Name="textBlock"
                   Width="200"
                   Height="30" />
    </ContentControl>
</Grid>


注意:如果 PreviewMouseUp 处理程序发生更改,使其始终更改颜色(例如,创建一个在两种不同颜色之间进行选择并在每次处理程序时切换的 bool被调用),则永远不会引发事件。例如:

private bool _toggle;

void contentControl_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
    contentControl.Foreground = _toggle ? Brushes.Red : Brushes.Green;
    _toggle = !_toggle;
}

有什么方法可以让PreviewMouseUp 处理程序设置颜色,但在第一次单击链接时仍会引发RequestNavigateClick 事件?

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

    我不知道确切这里发生了什么,但从症状中可以清楚地看出,更改ContentControl.Foreground 属性会中断鼠标事件的正常处理。当您设置属性值时,这会导致 WPF 决定应该忽略该事件(也许它将属性更改视为事件已被处理的指示),因此通常稍后会引发的事件不在提出的事实。

    鉴于此,在我看来,最明显的解决方法是将属性值的更改推迟到鼠标事件实际上已被完全处理之后,包括引发这些事件。我能想到的最明显的方法是稍后使用Dispatcher 调用该操作。

    即通过使用Dispatcher.InvokeAsync(),我们可以确保鼠标事件本身的处理在属性更改完成之前已完全处理,因为调度程序正忙于处理鼠标事件,并且在它被调用之前无法运行调用的委托鼠标事件结束。

    看起来像这样:

    void contentControl_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        Dispatcher.InvokeAsync(() =>
        {
            contentControl.Foreground = Brushes.Green;
        });
    }
    

    如果您将PreviewMouseUp 处理程序更改为上述处理程序,您应该会看到即使在第一次鼠标单击时也会引发事件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-07
      • 1970-01-01
      相关资源
      最近更新 更多