2016-04-18 13 views
3

Ich habe eine ItemsControl, deren ItemsPresenter auf das Ereignis MouseMove reagiert. Elemente werden innerhalb der Datenquelle verschoben. Wenn sich die Maus beim Verschieben von Elementen über dem Steuerelement befindet, wird das Ereignis MouseMove ausgelöst, obwohl sich die Maus nicht bewegt.Warum wird das MouseMove-Ereignis ausgelöst, wenn sich die Maus nicht bewegt?

Im Folgenden finden Sie ein Beispiel für das Problem.

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> 

Die 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; 
    } 
} 

Wenn Sie debug/diese ausführen, die Maus über die ItemsControl bewegen, und lassen Sie ihn dort, werden Sie im Ausgabefenster sehen dass das Ereignis MouseMove ausgelöst wird, während Elemente im Steuerelement verschoben werden.

Gründe dafür? Oder gibt es eine Möglichkeit, diese Ereignisse zu filtern und nur auf "echte" Mausbewegungen zu reagieren?

+1

ich aus der Maus Perspektive denke, es bewegt. – LarsTech

+0

Aber ist das Ereignis nicht aus Sicht der Steuerung, nicht der Maus? – WasGoodDone

+0

Können Sie die Position der Maus gleichzeitig ausgeben? Vielleicht gibt es sehr kleine kleine Mausbewegungen, die mit dem bloßen Auge nicht sichtbar sind, aber der Computer nimmt auf? –

Antwort

3

In Ihrem Beispiel sprudeln diese Ereignisse aus den untergeordneten Steuerelementen Ihres Element-Presenters, also aus TextBlocks. Wenn Sie dies tun:

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

Sie werden sehen, dass jedes Mal, Veranstaltungsoriginalquelle ist anders Textblock (0 1 2 3 4 5), und ist ein Textblock, die jetzt unter der Maus ist. Und aus der Perspektive dieses Textblocks wurde die Maus tatsächlich bewegt - sie war nicht drüber und wurde dann zu Ende. Ich stimme zu, dass es ein strittiges Verhalten ist und vielleicht sogar als Fehler angesehen werden kann. Um dies zu umgehen, am einfachsten ich denke, ist letzte Maus bewegen Position merken und prüfen, ob sie sich geändert hat:

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

Ah, das macht Sinn. Vielen Dank! – WasGoodDone

Verwandte Themen