2016-04-18 7 views
3

У меня есть ItemsControl, чья ItemsPresenter отвечает на событие MouseMove. Элементы перемещаются в источнике данных, и если мышь находится над элементом управления при перемещении элементов, это вызывает событие 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, и оставить его там, вы увидите в окне Output что событие MouseMove стреляет как элементы в сдвиге управления.

Любые причины для этого? Или есть способ отфильтровать эти события и реагировать только на «реальные» события перемещения мыши?

+1

Думаю, с точки зрения мыши она двигалась. – LarsTech

+0

Но разве это не событие с точки зрения управления, а не с мышью? – WasGoodDone

+0

Можете ли вы вывести положение мыши одновременно? Может быть, есть очень маленькие незначительные движения мыши, которые не видны невооруженным глазом, но компьютер поднимается? –

ответ

3

В вашем примере эти события пузырятся из дочерних элементов управления презентатором вашего объекта, то есть из 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), и является TextBlock, который сейчас находится под мышкой. И с точки зрения этого текстового блока мышь действительно была перемещена - она ​​не была над этим, а затем перевернулась. Я согласен, что спорно поведение, и, возможно, можно считать ошибку даже. Чтобы обойти это, проще всего вспомнить последнюю позицию перемещения мыши и проверить, не изменилось ли это:

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

А, это имеет смысл. Благодаря! – WasGoodDone