2010-11-21 7 views
5

Ho un UserControl WPF in cui cerco di realizzare il personalizzato MouseClick (perché non v'è alcuna MouseClick evento in un controllo WPF (Utente)) evento.'System.StackOverflowException' verificato in PresentationCore.dll

ho ottenuto il seguente:

alt text

Alcuni codice:

/// <summary> 
/// Occurs when users left clicks the MyControl. 
/// </summary> 
public event MouseButtonEventHandler MouseClick { add { AddHandler(MouseClickEvent, value); } remove { RemoveHandler(MouseClickEvent, value); } } 

    protected virtual void OnMouseClick(MouseButtonEventArgs e) 
    { 
     base.RaiseEvent(e); 
     //this.RaiseEvent(new RoutedEventArgs(MouseClickEvent, this)); 
    } 

    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) 
    { 
     base.OnMouseLeftButtonUp(e); 
     if (!this.movedAfterMouseDown) 
     { 
      OnMouseClick(e); 
     } 
     this.gotLeftButtonDown = false; 
     this.movedAfterMouseDown = false; 
    } 

Allora, dov'è il problema?

UPDATE 1

protected virtual void OnMouseClick(MouseButtonEventArgs e) 
{ 
    //base.RaiseEvent(e); 
    MouseButtonEventArgs args = new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, e.ChangedButton); 
    this.RaiseEvent(args); 
} 

valore non può essere null. Nome del parametro: RoutedEvent

alt text

UPDATE 2

Un altro evento personalizzato ho implementato con successo (lavoro senza problemi) - SelectedChanged:

static void OnIsSelectedChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
{ 
    var s = (MyControl)source; 

    s.RaiseEvent(new RoutedEventArgs(SelectedChangedEvent, s)); 
} 

UPDATE 3

sistema. Implementazione OnPreviewMouseDoubleClick di Windows.Controls.Control:

protected virtual void OnPreviewMouseDoubleClick(MouseButtonEventArgs e) 
{ 
    base.RaiseEvent(e); 
} 

Aggiornamento 5 (per le persone nella vasca)

class Foo : FrameworkElement 
{ 
    event EasterCameEvent; // I named it MouseClick 

    public DoSomething() 
    { 
     EasterCameArgs args= ... 

     if (Date.Now = EasterDate) 
      OnEasterCame(args) 
    } 

    protected virtual void OnEasterCame(EasterCameArgs e) 
    { 
     base.RaiseEvent(e); 
    } 
} 
+0

+1 per il titolo che contiene SO. – Moshe

risposta

3
protected virtual void OnMouseClick(MouseButtonEventArgs e) 
{ 
    MouseButtonEventArgs args = new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, e.ChangedButton); 

    // Don't forget this 
    args.RoutedEvent = MouseClickEvent; 

    base.RaiseEvent(args); 
} 
+0

Quindi * stava * rilanciando se stesso più e più volte? Impostando la proprietà routedevent, si attiva un evento completamente diverso piuttosto che lo stesso. –

+0

@Josh: questo solleverà l'evento una sola volta: 'base.RaiseEvent (args);' base.RaiseEvent non chiama mai OnMouse, perché non sa della sua esistenza. – serhio

+0

Stiamo parlando di due cose completamente diverse. Il mio problema non era con questo metodo qui. Era con il gestore OnLeftButtonUp. Questo chiama OnMouseClick che a sua volta chiama nuovamente OnLeftButtonUp. Potresti aver risolto il problema, ma capisci perché si stava rompendo? –

2

penso che sia in questa linea:

base.RaiseEvent(e); 

Se si sta gestendo il clic del mouse non si vuole sollevare nuovamente l'evento in quanto ciò semplicemente richiamerà l'handler di nuovo, il che aumenterà l'evento ....

+1

Invece di 'base.RaiseEvent (e)' dovresti probabilmente usare 'base.OnMouseClick (e)'. BTW, credo che dovresti essere in grado di dare un'occhiata ad alcuni stack di chiamate nel debugger per vedere le chiamate ricorsive. –

+0

@Colin Thomsen: e ... uomo, non c'è una base.OnMouseClick in un UserControl WPF. Questo è il motivo per cui ne ho dichiarato uno nel mio evento personalizzato 'MouseClick'. – serhio

+0

@serhio - Che cosa stai cercando di ottenere rilanciando l'evento? – ChrisF

3

È necessario rimuovere la base.RaiseEvent (e) da TUTTE le parti del controllo utente personalizzato. Questa è la causa dello stack overflow.

Se si eredita da UserControl, gli eventi di clic sono già stati implementati per l'utente. NON è necessario reimplementare. Potrebbe essere necessario gestirli, ma molto probabilmente non lo fai.

protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) 
{ 
    // handle the event if you need to do something with the data. 
    // this is not over-riding the event, this is attaching a custom handler to the event 
    this.gotLeftButtonDown = false; 
    this.movedAfterMouseDown = false; 
} 

Questo non supera l'evento. Questo è un gestore per quando viene sollevato l'evento! Gli utenti del tuo controllo scriveranno gestori proprio come questo. Non reimplementarlo. Non gestirlo nemmeno se non hai bisogno di fare qualcosa con i dati. Questi eventi sono già scritti per te.

Edit:

Mentre la mia risposta era sbagliata in quanto non risolve il problema, dovrebbe essere ancora utile per capire perché l'eccezione StackOverflow stava accadendo.

protected virtual void OnMouseClick(MouseButtonEventArgs e) 
{ 
    base.RaiseEvent(e); 
    /* this will raise the OnMouseLeftButtonUp event if the MouseButtonEventArgs 
     designates that it came from the MouseLeftButtonUp event. 
     That will then call the OnMouseLeftButtonUp because e.RoutedEvent equals 
     MouseLeftButtonUpEvent. 

     The accepted answer does the following, to stop OnMouseLeftButtonUp being 
     called again, and the whole process repeating itself in an infinite loop. 

     args.RoutedEvent = MouseClickEvent; 
     base.RaiseEvent(e); // No longer fires MouseLeftButtonUp, breaking cycle. 

     // Changes the event to be fired, avoiding the cycle of 
     // OnMouseLeftButtonUp -> OnMouseClick -> OnMouseLeftButtonUp etc 
    */ 
} 

protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) 
{ 
    base.OnMouseLeftButtonUp(e); 
    if (!this.movedAfterMouseDown) 
    { 
     OnMouseClick(e); // This will call OnMouseClick handler 
    } 
    this.gotLeftButtonDown = false; 
    this.movedAfterMouseDown = false; 
} 

Il flusso di controllo era: genera

  1. utente MouseLeftButtonUpEvent
  2. OnMouseClick si chiama all'interno gestore OnMouseLeftButtonUp
  3. OnMouseClick solleva evento MouseLeftButtonUp
  4. Goto 2.

Ilmodifiche risposta accettata a questo: genera

  1. utente MouseLeftButtonUpEvent
  2. OnMouseClick si chiama all'interno gestore OnMouseLeftButtonUp
  3. OnMouseClick cambia l'evento indirizzato al MouseClickEvent
  4. OnMouseClick solleva MouseClickEvent
  5. controllo riprende

Questo è ciò che stavo cercando di spiegare nei commenti su altre risposte. Se non fossi abbastanza chiaro, mi scuso per questo. Credo che serhio e io non fossimo sincronizzati perché stavo cercando di spiegare la causa dello stackvoverflow, quando cercava una correzione del codice. Correggimi se sbaglio.

+0

scusa per deluderti, ma non è implementato MouseClick sui controlli utente di WPF. – serhio

+0

+1. @serhio: qual è la differenza tra DoStuff e OnMouseClick? Niente! Questo è quello che sta succedendo qui. –

+0

@Billy ONeal: Andiamo, pleople. Chiaro il metodo ** OnMouseClick ** che NON ESISTE nella classe base, il * diverso * ** RaiseEvent ** mehtod che ESISTE. Mi scrivi circa la stessa DoStuff – serhio

Problemi correlati