2010-11-21 11 views
5

Mam WPF UserControl w którym staram się realizować niestandardową MouseClick (bo nie ma MouseClick wydarzenie na WPF (User) Kontrola) wydarzenie.„System.StackOverflowException” wystąpił w PresentationCore.dll

mam następujący:

alt text

jakiś kod:

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

Więc gdzie jest problem?

UPDATE 1

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

wartość nie może być zerowa. Nazwa parametru: RoutedEvent

alt text

UPDATE 2

Innym zdarzenie niestandardowe I wdrożone z powodzeniem (praca bez problemów) - SelectedChanged:

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

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

UPDATE 3

systemu. Implementacja OnPreviewMouseDoubleClick systemu Windows.Controls.Control:

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

Update 5 (dla osób w zbiorniku)

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 za tytuł zawierający SO. – Moshe

Odpowiedz

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

Czy zatem * ciągle się podnosił? Ustawiając właściwość routedevent, uruchamiasz zupełnie inne zdarzenie niż to samo. –

+0

@Josh: to podniesie zdarzenie tylko raz: 'base.RaiseEvent (args);' base.RaiseEvent nigdy nie wywołuje OnMouse, ponieważ nie wie o jego istnieniu. – serhio

+0

Mówimy o dwóch zupełnie różnych rzeczach. Mój problem nie dotyczył tej metody. To było z handler OnLeftButtonUp. To wywołuje OnMouseClick, który z kolei ponownie wywołuje OnLeftButtonUp. Być może udało Ci się rozwiązać problem, ale czy rozumiesz, dlaczego go zrywało? –

2

myślę, że to w tej linii:

base.RaiseEvent(e); 

Jeśli obsługa myszy kliknij nie chcą Podnieś wydarzenie ponownie, ponieważ to po prostu ponownie zadzwonisz do swojego przewodnika, co podniesie wydarzenie ...

+1

Zamiast 'base.RaiseEvent (e)' powinieneś prawdopodobnie używać 'base.OnMouseClick (e)'. BTW, Wierzę, że powinieneś móc rzucić okiem na niektóre stosy wywołań w debugerze, aby zobaczyć wywołania rekursywne. –

+0

@Colin Thomsen: e ... człowieku, nie ma bazy.OnMouseClick w UserControl WPF. Właśnie dlatego zadeklarowałem jeden w moim niestandardowym zdarzeniu "MouseClick". – serhio

+0

@serhio - Co próbujesz osiągnąć, ponownie biorąc udział w wydarzeniu? – ChrisF

3

Musisz usunąć bazę.RaiseEvent (e) z WSZYSTKICH części niestandardowej kontroli użytkownika. To jest przyczyną przepełnienia stosu.

Jeśli dziedziczysz z UserControl, zdarzenia kliknięcia są już zaimplementowane. NIE musisz ponownie wdrażać. Możesz sobie z nimi poradzić, ale najprawdopodobniej nie.

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

To nie przeładowuje imprezy. Jest to program do obsługi, gdy wydarzenie zostanie podniesione! Użytkownicy twojego sterowania będą pisać programy obsługi podobne do tego. Nie reimplementuj go. Nawet go nie obsługuj, chyba że musisz coś zrobić z danymi. Te wydarzenia są już napisane dla Ciebie.

Edit:

Chociaż moja odpowiedź jest nie tak, że to nie rozwiąże problemu, należy nadal być pomocne zrozumieć, dlaczego stackoverflow wyjątek dzieje.

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

Przepływ kontrola była:

  1. użytkownika generuje MouseLeftButtonUpEvent
  2. OnMouseClick nazywa ciągu OnMouseLeftButtonUp obsługi
  3. OnMouseClick podnosi wydarzenie MouseLeftButtonUp
  4. Goto 2.

The zaakceptowanych zmian odpowiedź na to:

  1. użytkownika generuje MouseLeftButtonUpEvent
  2. OnMouseClick nazywa ciągu OnMouseLeftButtonUp obsługi
  3. OnMouseClick powoduje zmianę kierowane wydarzenie MouseClickEvent
  4. OnMouseClick podnosi MouseClickEvent
  5. Kontrola wznawia

To właśnie starałem się wyjaśnić w komentarzach do innych odpowiedzi. Gdybym nie był wystarczająco jasny, przepraszam za to. Sądzę, że serhio i ja nie mogliśmy się zsynchronizować, próbując wyjaśnić przyczynę przepływu stosu, kiedy szukał poprawki do kodu. Popraw mnie, jeśli się mylę.

+0

Przykro mi to rozczarować, ale nie ma wdrożonego MouseClick na kontrolkach użytkownika WPF. – serhio

+0

+1. @Serhio: Jaka jest różnica między DoStuff i OnMouseClick? Nic! Tak się tutaj dzieje. –

+0

@Billy ONeal: Dalej, pleople. Wzywam w metodzie ** OnMouseClick **, która NIE WYSTĘPUJE w klasie bazowej, * innym * ** RaiseEvent **, który istnieje. Piszecie do mnie o tym samym DoStuff – serhio

Powiązane problemy