2010-11-21 23 views
5

Tôi có một WPF UserControl trong đó tôi cố gắng thực hiện các tùy chỉnh mouseclick (vì không có MouseClick sự kiện trên một Control WPF (User)) sự kiện.'System.StackOverflowException' xảy ra ở PresentationCore.dll

tôi đã nhận như sau:

alt text

Một số mã:

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

Vì vậy, mà là vấn đề?

CẬP NHẬT 1

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

Giá trị không thể null. tên Parameter: routedEvent

alt text

UPDATE 2

Một sự kiện tùy chỉnh khác mà tôi thực hiện thành công (làm việc mà không vấn đề) - SelectedChanged:

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

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

CẬP NHẬT 3

System. Triển khai OnPreviewMouseDoubleClick của Windows.Controls.Control:

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

Cập nhật 5 (đối với người trong bể)

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 cho tựa đề chứa SO. – Moshe

Trả lời

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

Vì vậy, nó * đã được * tái nâng cao bản thân hơn và hơn? Bằng cách đặt thuộc tính routedevent, bạn kích hoạt một sự kiện hoàn toàn khác thay vì giống nhau. –

+0

@Josh: điều này sẽ nâng cao sự kiện chỉ một lần: 'base.RaiseEvent (args);' base.RaiseEvent không bao giờ gọi OnMouse, bởi vì không biết sự tồn tại của nó. – serhio

+0

Chúng ta đang nói về hai điều hoàn toàn khác nhau. Vấn đề của tôi không phải với phương pháp này ở đây. Đó là với trình xử lý OnLeftButtonUp. Điều đó gọi OnMouseClick mà lần lượt gọi OnLeftButtonUp một lần nữa. Bạn có thể đã khắc phục vấn đề, nhưng bạn có hiểu tại sao nó bị phá vỡ không? –

2

Tôi nghĩ đó là trong dòng này:

base.RaiseEvent(e); 

Nếu bạn đang xử lý chuột nhấp chuột, bạn không muốn nâng cao sự kiện một lần nữa vì điều đó sẽ chỉ gọi cho người xử lý của bạn một lần nữa, điều này sẽ nâng cao sự kiện ....

+1

Thay vì 'base.RaiseEvent (e)', bạn nên sử dụng 'base.OnMouseClick (e)'. BTW, tôi tin rằng bạn sẽ có thể xem một số ngăn xếp cuộc gọi trong trình gỡ rối để xem các cuộc gọi đệ quy. –

+0

@Colin Thomsen: e ... người đàn ông, không có base.OnMouseClick trong một UserFrol WPF. Đây là lý do tại sao tôi tuyên bố một trong sự kiện 'MouseClick' tùy chỉnh của tôi. – serhio

+0

@serhio - Bạn đang cố gắng đạt được điều gì bằng cách nâng cao sự kiện? – ChrisF

3

Bạn cần phải loại bỏ cơ sở.RaiseEvent (e) từ TẤT CẢ các phần của điều khiển người dùng tùy chỉnh của bạn. Đó là nguyên nhân gây ra tràn ngăn xếp.

Nếu bạn đang kế thừa từ UserControl, các sự kiện nhấp chuột đã được triển khai cho bạn. Bạn KHÔNG cần phải triển khai lại. Bạn CÓ THỂ cần phải xử lý chúng mặc dù, nhưng có lẽ bạn không.

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

Điều này không quá sự kiện. Đây là một xử lý cho khi sự kiện được nâng lên! Người dùng điều khiển của bạn sẽ viết các trình xử lý giống như trình xử lý này. Đừng reimplement nó. Thậm chí không xử lý nó trừ khi bạn cần phải làm điều gì đó với dữ liệu. Những sự kiện này được viết cho bạn rồi.

Edit:

Trong khi câu trả lời của tôi đã sai ở chỗ nó không khắc phục được vấn đề này, nó vẫn cần được giúp đỡ để hiểu TẠI SAO ngoại trừ stackoverflow đang xảy ra.

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

Các dòng điều khiển là:

  1. tài khoản tạo MouseLeftButtonUpEvent
  2. OnMouseClick được gọi trong OnMouseLeftButtonUp handler
  3. OnMouseClick tăng MouseLeftButtonUp kiện
  4. Chuyển đến 2.

Các thay đổi câu trả lời được chấp nhận như sau:

  1. tài khoản tạo MouseLeftButtonUpEvent
  2. OnMouseClick được gọi là trong phạm vi xử lý OnMouseLeftButtonUp
  3. OnMouseClick những thay đổi trường hợp chuyển đến MouseClickEvent
  4. OnMouseClick tăng MouseClickEvent
  5. kiểm soát sơ yếu lý lịch

Đây là những gì tôi đã cố gắng giải thích trong các ý kiến ​​về câu trả lời khác. Nếu tôi không đủ rõ ràng, tôi xin lỗi vì điều đó. Tôi tin rằng serhio và tôi đã không đồng bộ trong đó tôi đã cố gắng để giải thích nguyên nhân của stackvoverflow, khi ông đang tìm kiếm một sửa chữa cho mã. Đúng nếu tôi sai.

+0

xin lỗi bạn đã thất vọng, nhưng không có MouseClick được thực hiện trên các điều khiển người dùng WPF. – serhio

+0

+1. @ serhio: Sự khác nhau giữa DoStuff và OnMouseClick là gì? Không có gì! Đó là những gì đang xảy ra ở đây. –

+0

@Billy ONeal: Thôi nào, pleople. Tôi gọi phương thức ** OnMouseClick ** KHÔNG tồn tại trong lớp cơ sở, * khác * ** RaiseEvent ** mehtod mà EXISTS. Bạn viết cho tôi về cùng một DoStuff – serhio

Các vấn đề liên quan