【问题标题】:Why does MouseMove event fire when mouse is not moving鼠标不移动时为什么会触发 MouseMove 事件
【发布时间】:2016-04-18 19:31:48
【问题描述】:

我有一个ItemsControl,其ItemsPresenter 响应MouseMove 事件。项目在数据源中移动,如果在移动项目时鼠标悬停在控件上,即使鼠标没有移动,也会触发 MouseMove 事件。

下面是一个演示问题的示例。

XAML:

<ItemsControl Name="ladder" ItemsSource="{Binding Rows}">
    <ItemsControl.Template>
        <ControlTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <TextBlock Text="Header" Grid.Column="0" />
                <ItemsPresenter Grid.Row="1" 
                                MouseMove="OnMouseMove"/>
            </Grid>                 
        </ControlTemplate>
    </ItemsControl.Template>
</ItemsControl>

C#:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        Rows.Add(new Row { Name = "0" });
        Rows.Add(new Row { Name = "1" });
        Rows.Add(new Row { Name = "2" });
        Rows.Add(new Row { Name = "3" });
        Rows.Add(new Row { Name = "4" });

        DispatcherTimer t = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(1000) };
        t.Tick += T_Tick;
        t.Start();
    }

    private void T_Tick(object sender, EventArgs e)
    {
        Rows.Move(4, 0);
    }

    private void OnMouseMove(object sender, MouseEventArgs e)
    {
        Debug.WriteLine(e.Timestamp);
    }

    public ObservableCollection<Row> Rows { get; set; } = new ObservableCollection<Row>();
}

public class Row
{
    public string Name { get; set; }

    public override string ToString()
    {
        return Name;
    }
}

如果您调试/运行它,将鼠标移到ItemsControl 上,然后将其留在那里,您将在“输出”窗口中看到MouseMove 事件正在触发,因为控件中的项目四处移动。

有什么理由吗?或者有没有办法过滤掉这些事件,只响应“真实的”鼠标移动事件?

【问题讨论】:

  • 我猜从鼠标的角度来看,它移动了。
  • 但是从控件的角度来看,事件不是鼠标的吗?
  • 可以同时输出鼠标的位置吗?也许有肉眼看不到的非常微小的鼠标移动,但计算机正在启动?

标签: c# wpf mousemove


【解决方案1】:

在您的示例中,这些事件是从您的项目演示者的子控件冒泡的,即来自 TextBlocks。如果你这样做:

private void OnMouseMove(object sender, MouseEventArgs e)
{
    var tb=(TextBlock)e.OriginalSource;
    var lastMove = e.GetPosition((IInputElement)e.OriginalSource);
    Debug.WriteLine(tb.Text + ":" + lastMove);
}

您会看到每次原始事件源都是不同的文本块(0 1 2 3 4 5),并且是现在在鼠标下的文本块。从这个文本块的角度来看,鼠标确实被移动了——它不是在它上面,而是在它上面。我同意这是有争议的行为,甚至可能被认为是错误。要解决这个问题,我认为最简单的方法是记住最后一次鼠标移动位置并检查它是否已更改:

private Point _lastMove;
private void OnMouseMove(object sender, MouseEventArgs e)
{                        
    var p = e.GetPosition((IInputElement)sender);
    if (_lastMove != p) {
        // really moved
        _lastMove = p;
    }
}

【讨论】:

    猜你喜欢
    • 2012-02-04
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 2021-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-26
    相关资源
    最近更新 更多