2011-07-20 38 views
20

Tôi đang viết điều khiển tùy chỉnh và tôi muốn điều khiển chuyển từ trạng thái chỉnh sửa sang trạng thái bình thường khi người dùng nhấp vào kiểm soát. Tôi đang xử lý sự kiện LostFocus và giúp khi người dùng bỏ đi hoặc nếu họ nhấp vào một điều khiển khác có thể tập trung. Nhưng nếu họ không bấm vào một cái gì đó Focusable, nó sẽ không chuyển ra khỏi trạng thái chỉnh sửa của nó. Vì vậy, tôi có hai giải pháp trong tâm trí:Làm cách nào một điều khiển có thể xử lý một cú nhấp chuột bên ngoài điều khiển đó?

  • Đi bộ lên cây để các yếu tố nhất hàng đầu khi nó đi vào một trạng thái chỉnh sửa và thêm một handler cho MouseDownEvent (và xử lý "xử lý" các sự kiện). Trong trình xử lý, tôi muốn kiểm soát trạng thái chỉnh sửa của nó và loại bỏ trình xử lý khỏi phần tử trên cùng. Điều này có vẻ như một chút của một hack, nhưng nó có lẽ sẽ làm việc tốt.

Ví dụ mã:

private void RegisterTopMostParentMouseClickEvent() 
{ 
    _topMostParent = this.FindLastVisualAncestor<FrameworkElement>(); 
    if (_topMostParent == null) 
     return; 
    _topMostParent.AddHandler(Mouse.MouseDownEvent, new MouseButtonEventHandler(CustomControlMouseDownEvent), true); 
} 

private void UnRegisterTopMostParentMouseClickEvent() 
{ 
    if (_topMostParent == null) 
     return; 
    _topMostParent.RemoveHandler(Mouse.MouseDownEvent, new MouseButtonEventHandler(CustomControlMouseDownEvent)); 
    _topMostParent = null; 
} 
  • Sử dụng Mouse.PreviewMouseDownOutsideCapturedElement và thêm một handler để kiểm soát của tôi. Trong trình xử lý, tôi muốn kiểm soát trạng thái chỉnh sửa của nó. Nhưng tôi dường như không nhận được sự kiện để bắn. Khi nào Mouse.PreviewMouseDownOutsideCapturedElement bị khởi động?

Ví dụ mã:

AddHandler(Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler(EditableTextBlockPreviewMouseDownOutsideCapturedElementEvent), true); 

Trả lời

12

Capture chuột. Khi một đối tượng chụp chuột, tất cả các sự kiện liên quan đến chuột sẽ được xử lý như thể đối tượng có chụp chuột thực hiện sự kiện, ngay cả khi con trỏ chuột trên đối tượng khác.

+2

Vì vậy, điều này làm việc hoàn hảo. Tất cả những gì tôi phải làm là Chụp chuột khi tôi vào chế độ chỉnh sửa, sau đó WPF tự động lấy nét ra khỏi phần tử khi bạn nhấp vào bên ngoài phần tử đó. Sau khi tôi mất tập trung, tôi chỉ cần cẩn thận với ReleaseMouseCapture(). Cảm ơn! – chrislarson

+3

Điều duy nhất khác mà tôi phải cẩn thận là khi bạn nhấn phím cửa sổ hoặc một ứng dụng khác khởi chạy, tôi sẽ mất hoạt động chụp chuột mà không ngăn điều khiển của tôi ở trạng thái chỉnh sửa. Vì vậy, tôi đã phải xử lý sự kiện IsMouseCapturedChanged. Ví dụ: 'private void CustomControlIsMouseCapturedChanged (đối tượng người gửi, DependencyPropertyChangedEventArgs e) { nếu ((bool) e.NewValue == false) { IsEditing = false; } } ' – chrislarson

0

Tôi sẽ tiếp cận cách này theo cách khác - có biểu mẫu có chứa điều khiển xóa tiêu điểm khỏi điều khiển khi người dùng nhấp vào một phần khác của biểu mẫu.

Có sự kiểm soát thực sự tập trung lỏng lẻo là xa sạch hơn so với cố gắng để có kiểm soát "mô phỏng" tập trung bị mất trong các tình huống nhất định, khi trong thực tế nó đã không. Hãy nhớ rằng trừ khi điều khiển đã thực sự mất tập trung nó vẫn sẽ chấp nhận những thứ như đầu vào bàn phím.

+0

Vì vậy, bạn có nói rằng tôi làm cho biểu mẫu có thể tập trung không? Bởi vì tiêu điểm sẽ không bị lấy đi tự động trừ khi nó được chuyển sang một yếu tố khác, đúng không? Ví dụ: điều này sẽ không tập trung vào TextBox: ' \t \t \t \t ' – chrislarson

+0

@chrislarson Bạn có thể đặt một điều khiển khác (ví dụ như một nhãn, có thể là một nhãn không có văn bản) để được tập trung - xem [Có cách nào để làm cho phần tử giao diện người dùng bị mất tập trung] hay không (http://stackoverflow.com/questions/ 2664460/wpf-là-có-một-cách-to-nguyên-an-ui-yếu tố-to-lỏng-tập trung-không-thay đổi-the-fo) – Justin

+0

Điều đó chắc chắn tốt với tôi, tôi vẫn có thể chỉ căn cứ hay không kiểm soát ở trạng thái chỉnh sửa bởi nó có tập trung hay không. Nhưng tôi vẫn cần một cách đáng tin cậy để kiểm soát mất tập trung khi người dùng nhấp vào bên ngoài kiểm soát. – chrislarson

30

Chỉ cần làm rõ câu trả lời cung cấp về tập trung chuột - đó là hữu ích nhưng tôi đã phải làm một số việc đào bới thêm + mucking về để có được một cái gì đó mà thực sự làm việc:

Tôi đã cố gắng để thực hiện một cái gì đó giống như một combobox và cần thiết hành vi tương tự - để có được thả xuống để disapear khi nhấp vào cái gì khác, mà không có sự kiểm soát có kiến ​​thức về những gì khác được.

tôi đã có sự kiện sau đây cho một nút thả xuống:

private void ClickButton(object sender, RoutedEventArgs routedEventArgs) 
    { 
     //do stuff (eg activate drop down) 
     Mouse.Capture(this, CaptureMode.SubTree); 
     AddHandler(); 
    } 

Các CaptureMode.SubTree có nghĩa là bạn chỉ nhận được những sự kiện nằm ngoài sự kiểm soát và bất kỳ hoạt động chuột trong việc kiểm soát được qua những thứ như bình thường . Bạn không có tùy chọn để cung cấp Enum này trong CaptureMouse của UIElement, điều này có nghĩa là bạn sẽ nhận được cuộc gọi đến HandleClickOutsideOfControl INSTEAD của các cuộc gọi đến bất kỳ điều khiển con hoặc xử lý khác trong vòng kiểm soát. Đây là trường hợp ngay cả khi bạn không đăng ký các sự kiện mà họ đang sử dụng - đầy đủ Chụp chuột là một chút quá nhiều!

private void AddHandler() 
    { 
     AddHandler(Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler(HandleClickOutsideOfControl), true); 
    } 

Bạn cũng sẽ cần phải bỏ qua + xóa trình xử lý tại các điểm thích hợp nhưng tôi đã để nó ở đây để rõ ràng/ngắn gọn.

Cuối cùng trong trình xử lý, bạn cần phải nhả lại ảnh chụp.

private void HandleClickOutsideOfControl(object sender, MouseButtonEventArgs e) 
    { 
     //do stuff (eg close drop down) 
     ReleaseMouseCapture(); 
    } 
+7

Một số điều khiển như TextBox có xu hướng giải phóng caputre khi nhấp vào, do đó bạn sẽ phải gắn lại trình xử lý mỗi lần điều khiển tăng sự kiện 'LostMouseCapture'. Chỉ là quan sát của tôi. –

0

Tôi thường nhận được cửa sổ chính và thêm trình xử lý xem trước, ngay cả khi đã được xử lý. Đôi khi khi MouseCapture không đủ, kỹ thuật này có ích:

Window.GetWindow(this).AddHandler 
(
    UIElement.MouseDownEvent, 
    (MouseButtonEventHandler)TextBox_PreviewMouseDown, 
    true 
); 
Các vấn đề liên quan