2010-11-21 12 views
5

tengo un control de usuario de WPF en el que trato de poner en práctica la costumbre MouseClick (porque no hay MouseClick evento en un control WPF (Usuario)) evento.'System.StackOverflowException' se ha producido en PresentationCore.dll

me dieron el siguiente:

alt text

Algunos código:

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

Entonces, ¿dónde está el problema?

ACTUALIZACIÓN 1

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

El valor no puede ser nulo. Nombre de parámetro: RoutedEvent

alt text

ACTUALIZACIÓN 2

Un otro evento personalizado que he implementado con éxito (trabajo sin problemas) - SelectedChanged:

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

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

ACTUALIZACIÓN 3

sistema. Implementación de Windows.Controls.Control OnPreviewMouseDoubleClick:

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

Update 5 (para las personas en el tanque)

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 para el título que contiene SO. – Moshe

Respuesta

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

Entonces, * ¿* estaba * resucitándose una y otra vez? Al establecer la propiedad routedevent, activa un evento completamente diferente en lugar de lo mismo. –

+0

@Josh: esto elevará el evento solo una vez: 'base.RaiseEvent (args);' base.RaiseEvent nunca llama a OnMouse, porque no sabe de su existencia. – serhio

+0

Estamos hablando de dos cosas completamente diferentes. Mi problema no fue con este método aquí. Fue con el controlador OnLeftButtonUp. Eso llama a OnMouseClick que a su vez llama a OnLeftButtonUp nuevamente. Puede haber solucionado el problema, pero ¿entiende por qué se estaba rompiendo? –

2

creo que es en esta línea:

base.RaiseEvent(e); 

Si usted está manejando el clic de ratón que no quiere plantee de nuevo el evento, ya que eso simplemente llamará nuevamente a su controlador, lo que provocará el evento ....

+1

En lugar de 'base.RaiseEvent (e)' probablemente deberías usar 'base.OnMouseClick (e)'. BTW, creo que debería poder echar un vistazo a algunas de las llamadas en el depurador para ver las llamadas recursivas. –

+0

@ Colin Thomsen: e ... hombre, no hay base.OnMouseHaga clic en un UserControl de WPF. Es por eso que declare uno en mi evento personalizado 'MouseClick'. – serhio

+0

@serhio - ¿Qué intenta lograr volviendo a plantear el evento? – ChrisF

3

Debe quitar la base.RaiseEvent (e) desde TODAS las partes de su control de usuario personalizado. Esa es la causa del desbordamiento de la pila.

Si está heredando de UserControl, los eventos de clic ya están implementados para usted. NO es necesario volver a implementarlo. Puede que necesites manejarlos, pero probablemente no lo hagas.

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

Esto no anula el evento. ¡Este es un controlador para cuando se plantea el evento! Los usuarios de su control escribirán manejadores como este. No lo vuelvas a implementar. Ni siquiera lo maneje a menos que necesite hacer algo con los datos. Estos eventos ya están escritos para ti.

Editar:

Mientras que mi respuesta era malo en que no se soluciona el problema, que aún debe ser útil para entender por qué la excepción stackoverflow estaba sucediendo.

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

El flujo de control fue:

  1. usuario genera MouseLeftButtonUpEvent
  2. OnMouseClick se llama dentro de manejador OnMouseLeftButtonUp
  3. OnMouseClick plantea evento MouseLeftButtonUp
  4. Goto 2.

El cambios respuesta aceptada a esto:

  1. usuario genera MouseLeftButtonUpEvent
  2. OnMouseClick se llama dentro manejador OnMouseLeftButtonUp
  3. OnMouseClick cambia el evento enrutado a MouseClickEvent
  4. OnMouseClick plantea MouseClickEvent
  5. control reanuda

Esto es lo que estaba tratando de explicar en comentarios sobre otras respuestas. Si no fui lo suficientemente claro, me disculpo por eso. Creo que Serio y yo estábamos fuera de sincronización porque estaba tratando de explicar la causa del stackvoverflow, cuando estaba buscando una solución al código. Corrígeme si estoy equivocado.

+0

siento decepcionarte, pero no hay MouseClick implementado en los controles de usuario de WPF. – serhio

+0

+1. @serhio: ¿Cuál es la diferencia entre DoStuff y OnMouseClick? ¡Nada! Eso es lo que está pasando aquí. –

+0

@Billy ONeal: Vamos, pleople. Llamo al método ** OnMouseClick ** que NO EXISTE en la clase base, el * diferente * ** evento RaiseEvent ** que EXISTE. Usted me escribe acerca de la misma DoStuff – serhio

Cuestiones relacionadas