2011-02-10 26 views
5

Tôi đã tạo một hành vi tùy chỉnh (không pha trộn) để kéo UIElements và nhận được hình thu nhỏ mờ của những gì bạn đang kéo dưới con trỏ (phiên bản kết hợp di chuyển đối tượng đích không phải là Tôi cần)Hành vi Silverlight onDetaching override không được gọi là

Anyhoo, mã thực sự rất đơn giản và hoạt động độc đáo, vấn đề tôi gặp phải là onDetaching() không được gọi, điều này có nghĩa là sự kiện của tôi đối với UIElement hiện chưa được mở.

Điều này làm tôi lo lắng một chút vì tôi đoán lý do duy nhất tại sao hành vi không bị tách ra là bởi vì nó vẫn đang được tham chiếu bởi một cái gì đó. Nó không phải là UIElement nó tự mặc dù chúng tôi đã có vấn đề rò rỉ với nó ở một giai đoạn nhưng chúng tôi đã giải quyết chúng và điều này được làm rõ thông qua WinDbg.

Điều thú vị duy nhất (?) Về nó là hành vi được gắn vào một hình ảnh trong một mục điều khiển, nhưng điều này không tạo nên sự khác biệt đúng không?

Đây là mã hiện tại của tôi:

public class DragBehavior : Behavior<UIElement> 
{ 
    private const double DRAG_DISTANCE = 20; 
    private const int DRAG_ICON_HEIGHT = 100; 

    Point m_firstPoint; 
    private bool m_isDragging = false; 
    private Popup m_dragPopup = null; 
    private Image m_draggedImage;   

    protected override void OnAttached() 
    { 
     this.AssociatedObject.MouseLeftButtonDown += new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonDown); 
     this.AssociatedObject.MouseMove += new MouseEventHandler(AssociatedObject_MouseMove); 
     this.AssociatedObject.MouseLeftButtonUp += new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonUp); 

     base.OnAttached(); 
    } 

    void AssociatedObject_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     m_firstPoint = e.GetPosition(null); 
     m_isDragging = true; 
    } 

    void AssociatedObject_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (m_isDragging) 
     { 
      Point currentPosition = e.GetPosition(null); 

      if (m_dragPopup == null) 
      { 
       double deltaX = currentPosition.X - m_firstPoint.X; 
       double deltaY = currentPosition.Y - m_firstPoint.Y; 

       double movement = Math.Sqrt((deltaX * deltaX) + (deltaY * deltaY)); 
       if (movement > DRAG_DISTANCE) 
       { 
        // Get a screen shot of the element this behaviour is attached to 
        WriteableBitmap elementScreenshot = new WriteableBitmap(AssociatedObject, null); 

        // Create an image out of it 
        m_draggedImage = new Image(); 
        m_draggedImage.Height = DRAG_ICON_HEIGHT; 
        m_draggedImage.Stretch = Stretch.Uniform; 
        m_draggedImage.Source = elementScreenshot; 
        m_draggedImage.Opacity = 0.4; 

        // Add the image to the popup 
        m_dragPopup = new Popup(); 
        m_dragPopup.Child = m_draggedImage; 

        m_dragPopup.IsOpen = true; 
        m_dragPopup.UpdateLayout(); 

        m_dragPopup.HorizontalOffset = currentPosition.X - m_draggedImage.ActualWidth/2; 
        m_dragPopup.VerticalOffset = currentPosition.Y - m_draggedImage.ActualHeight/2; 

        AssociatedObject.CaptureMouse(); 
       } 
      } 
      else 
      { 
       m_dragPopup.HorizontalOffset = currentPosition.X - m_draggedImage.ActualWidth/2; 
       m_dragPopup.VerticalOffset = currentPosition.Y - m_draggedImage.ActualHeight/2; 
      } 
     } 
    } 

    void AssociatedObject_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
    { 
     if (m_isDragging == true && m_dragPopup != null) 
     { 
      m_isDragging = false; 
      m_dragPopup.IsOpen = false; 
      m_dragPopup = null; 
     } 

     AssociatedObject.ReleaseMouseCapture(); 

     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
     GC.Collect(); 
    } 

    protected override void OnDetaching() 
    { 
     this.AssociatedObject.MouseLeftButtonDown -= new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonDown); 
     this.AssociatedObject.MouseMove -= new MouseEventHandler(AssociatedObject_MouseMove); 
     this.AssociatedObject.MouseLeftButtonUp -= new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonUp); 

     base.OnDetaching(); 
    } 
} 

Tôi biết hai bài viết mà tôi đã nhìn thấy về vấn đề này ...

này một - forums.silverlight.net/forums/p/142038/ 317146.aspx không giúp đỡ như tôi đã cố gắng buộc một GC để avail không có, và điều này một - Automatically calling OnDetaching() for Silverlight Behaviors Tôi không thực sự nhận được sự bùng nổ của họ khi họ yêu cầu bồi thường của nó hooking lên của UIElement với hành vi gây ra nó, nhưng chắc chắn khi tài liệu tham khảo gốc UIElement bị hỏng, tham chiếu gốc đến hành vi cũng sẽ bị loại bỏ và do đó cả hai trở nên dễ dàng cho GC.

Tôi đã hy vọng điều này sẽ đơn giản, nhưng nếu không, tôi sẽ bắt đầu với WinDbg để xem điều gì đang xảy ra!

Bất kỳ trợ giúp nào được đánh giá cao! :)

Xin cảm ơn,

Andy.

+1

Không ai có thể giúp bạn? Đoán tôi sẽ cố gắng đặt ra trong các diễn đàn Silverlight! Tôi sẽ cập nhật chủ đề này nếu tôi nhận được bất cứ nơi nào! – Andy

Trả lời

0

Bạn không hiển thị vị trí Detach đang được gọi. Một cái gì đó cần phải thực sự gọi object.Detach() (DragBehavior) cho phương thức OnDetaching() được gọi.

Nếu bạn muốn tách nó trong trình xử lý sự kiện AssociatedObject_MouseLeftButtonUp, bạn có thể gọi tách ở cuối phương thức miễn là bạn thực sự không cần phải làm gì hơn với nó.

void AssociatedObject_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
{ 
    if (m_isDragging == true && m_dragPopup != null) 
    { 
     m_isDragging = false; 
     m_dragPopup.IsOpen = false; 
     m_dragPopup = null; 
    } 

    AssociatedObject.ReleaseMouseCapture(); 

    this.Detach() 
} 

Tôi chắc chắn sẽ không được thực hiện bất kỳ cuộc gọi đến GC mà có thể có một tác động hiệu quả rất lớn.

+4

Tôi nghĩ đó là điểm mà anh ấy đang làm. Silverlight nên gọi là 'Detach' khi khung nhìn được lấy ra khỏi cây thị giác. –

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