簡體   English   中英

為什么鼠標移動時MouseMove事件會觸發

[英]Why does MouseMove event fire when mouse is not moving

我有一個ItemsControlItemsPresenter響應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事件正在觸發,因為控件中的項目會轉移。

有什么理由嗎? 或者有沒有辦法過濾這些事件,只響應“真正的”鼠標移動事件?

在您的示例中,這些事件是從您的項目演示者的子控件冒泡,即來自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;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM