2010-04-13 31 views
13

Tôi có thao tác kéo/thả trên Canvas có nghĩa vụ phải làm gì đó khi đối tượng bị kéo vào và ra khỏi nó. Vấn đề của tôi là các sự kiện DragEnter/DragLeave tiếp tục kích hoạt khi con chuột di chuyển đối tượng qua nó, không chỉ khi nhập/thoát. Chuột di chuyển nhanh hơn, các sự kiện càng thường xuyên kích hoạt.DragDrop - DragEnter/DragLeave Events tiếp tục bắn

Sự kiện Canvas DragOver di chuyển Canvas.Top/Left của DraggedObject và tôi nghĩ rằng đó có thể là vấn đề của tôi, nhưng tôi không chắc chắn làm thế nào tôi sẽ sửa lỗi này.

+0

Bạn có thể nói cho chúng tôi biết bạn có thể đề xuất phương án thay thế. –

+0

Tôi có một canvas với một loạt các Panels trên đó. Các bảng có thể được kéo xung quanh để sắp xếp lại chúng, hoặc các bảng mới có thể được thêm bằng cách kéo một bảng mới từ một hộp danh sách lên khung vẽ. Bạn cũng có thể xóa chúng bằng cách kéo các ô ra khỏi Canvas và quay lại Hộp danh sách. – Rachel

Trả lời

15

Đây là chuỗi các sự kiện:

  1. của bạn di chuyển chuột từ nơi mà bạn nhấp vào nó trên Panel. Không có sự kiện nào xảy ra.
  2. Con chuột của bạn đạt đến cạnh của Bảng và đi vào Canvas. Sự kiện DragEnter kích hoạt trên Canvas.
  3. Bộ xử lý DragEnter của bạn di chuyển Bảng điều khiển để nó bây giờ là dưới con chuột. Vì chuột không còn trên Canvas (nó nằm trên Bảng điều khiển), sự kiện DragLeave sẽ kích hoạt.
  4. Con chuột của bạn di chuyển xa hơn, tiếp cận lại cạnh của Bảng điều khiển. Lặp lại bước 2 và 3.

Bạn di chuyển chuột càng nhanh thì càng có nhiều sự kiện bạn sẽ nhận được. Bản chất của vấn đề của bạn là việc kéo thả sử dụng thử nghiệm hit và bằng cách di chuyển bảng điều khiển của bạn, bạn sẽ đánh bại khả năng kiểm tra lần truy cập để xem "phía sau" bảng điều khiển của bạn để biết vùng chứa đang bị rơi vào.

Giải pháp là sử dụng mã của riêng bạn để xử lý kéo và thả, điều này thực sự không khó chút nào. Công cụ kiểm tra hit của WPF đủ mạnh để thực hiện kiểm tra hit phía sau đối tượng hiện tại nhưng kéo thả không sử dụng chức năng này. Tuy nhiên, bạn có thể sử dụng trực tiếp bằng cách sử dụng quá tải VisualTreeHelper.HitTest mất HitTestFilterCallbackHitTestResultCallback. Chỉ cần vượt qua nó một bộ lọc mà bỏ qua bất kỳ số truy cập trong bảng điều khiển được kéo.

Tôi nhận thấy rằng đối với các kịch bản như bạn mô tả, việc kéo thả bằng cách xử lý sự kiện chuột thực sự dễ dàng hơn việc sử dụng DoDragDrop tích hợp vì bạn không phải đối phó với độ phức tạp (DataObject, DragDropEffects, QueryContinueDrag, v.v.) Sự phức tạp bổ sung này rất quan trọng để cho phép các tình huống kéo giữa các ứng dụng và các quy trình, nhưng không giúp bạn cho những gì bạn đang làm.

Đây là giải pháp đơn giản:

  1. On MouseDown với nút trái xuống, ghi lại vị trí (trên MouseLeave xóa vị trí)
  2. On MouseMove với {nút bên trái xuống, vị trí ghi, chuột hiện tại vị trí khác bởi nhiều hơn delta} thiết lập một cờ nói rằng hoạt động kéo đang được tiến hành & chụp chuột
  3. Trên MouseMove với thao tác kéo đang tiến hành, sử dụng thử nghiệm hit để xác định vị trí bảng điều khiển của bạn (bỏ qua bảng điều khiển) và điều chỉnh nuôi dạy con và vị trí phù hợp.
  4. On MouseUp với thao tác kéo cơ bản dở dang, nhả chụp chuột và rõ ràng là "hoạt động kéo là cơ bản dở dang" cờ

Thưởng thức.

+0

Cảm ơn bạn, đó chính là điều tôi đang tìm kiếm! Tôi đã chuyển đổi thuộc tính kéo/thả của mình để sử dụng MouseEvents thay vì DragEvents và cho tôi kết quả tôi đang tìm kiếm. Tôi đã có một số ban đầu đã có một số mối quan tâm làm như vậy bởi vì tôi đã kéo các đối tượng databound và các lớp tùy chỉnh, nhưng tất cả đều đến thông qua tốt. – Rachel

2

Tôi thấy cần thêm câu trả lời chính xác hơn cho những gì đang diễn ra, tôi cũng sẽ thêm cùng một câu trả lời đó vào các câu hỏi khác liên quan đến vấn đề này.

Ok, đây là những gì xảy ra:

  1. Bạn tạo một thao tác kéo-thả.
  2. Khi bạn kéo thả, bạn muốn nội dung nào đó hiển thị dọc theo con chuột của mình.
  3. Phần tử hình ảnh đó đang được thêm vào lưới hoặc bảng điều khiển trên sự kiện Kéo-Enter và đang bị xóa trên sự kiện Kéo-Để.
  4. Khi nó đang được đặt dưới chuột bạn sẽ nhận được một sự kiện kéo nghỉ là yếu tố bạn vẽ thực sự đánh cắp các thao tác kéo-thả ..

Giải pháp: Hãy chắc chắn rằng IsEnabled=false cho các phần tử bạn vẽ dưới con chuột.
Bằng cách đó nó sẽ không bắt bạn hoạt động kéo thả và bạn sẽ không nhận được hiệu ứng nhấp nháy.

2

Đây là một chút cũ, nhưng tôi đã có cùng một vấn đề. Tôi đang sử dụng một hình bóng để chỉ ra nơi mà một vật kéo được kéo đến. Tôi sẽ cho phép adorner trong DragEnter, sau đó ngay lập tức đăng ký một DragLeave và vô hiệu hóa các adorner, sau đó một DragEnter ...

IsEnabled = false không làm việc cho tôi, nhưng IsHitTestVisible = false đã làm. Tôi đặt điều này vào trong công trình xây dựng của adorner của tôi, và bây giờ tất cả đều hoạt động tốt đẹp:

public DragDropAdorner(UIElement adornedElement) : base(adornedElement) 
{ 
    _layer = AdornerLayer.GetAdornerLayer(AdornedElement); 
    _layer.IsEnabled = false; 
    _layer.IsHitTestVisible = false; 
} 
+0

Sửa chữa đơn giản này thực sự làm việc cho tôi và phù hợp với nhu cầu của tôi. Cảm ơn bạn. –