2011-02-10 17 views
5

我創建了一個自定義的行爲(不混合)用於拖動UI元素和得到你的光標拖動下什麼(混合版的半透明的縮略圖能戰勝不被稱爲移動目標對象,是不是有什麼我需要)Silverlight的行爲onDetaching

Anyhoo,代碼實際上很簡單,很好地工作,我遇到的問題是onDetaching()沒有被調用,這意味着我的UIElement事件不會被解除。

這讓我擔心了一點,因爲我猜的唯一原因未被分離的行爲是因爲它仍然被一些引用。它不應該是它自己的UIElement,因爲我們在一個階段遇到了滲漏問題,但現在我們已經解決了這個問題,並且通過WinDbg進行了澄清。

關於它的唯一有趣的(?)的是行爲附加到在項目控制的圖像,但這不應該有所作爲嗎?

這裏是我當前的代碼:

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

我知道,我已經看到了這個兩個職位的...

這一個 - forums.silverlight.net/forums/p/142038/ 317146.aspx並沒有幫助,因爲我試圖強制GC無濟於事,而這一個 - Automatically calling OnDetaching() for Silverlight Behaviors我並沒有真正得到他們的探索,因爲他們聲稱它的UIElement的行爲導致它的掛鉤,但當根引用UIElement被破壞時,行爲的根引用也將被刪除,因此兩者都可以成爲GC的合格對象。

我希望this'd是簡單的,但如果沒有,我會開始使用WinDbg的,看看有什麼實際發生的!

任何幫助非常感謝! :)

謝謝,

安迪。

+1

沒人能幫忙嗎?猜猜我會嘗試在Silverlight論壇中定位!我會更新這個線程,如果我得到任何地方! – Andy 2011-02-16 09:30:17

回答

0

你不顯示在拆離正從調用。有些事情需要實際調用object.Detach()(DragBehavior)來調用OnDetaching()方法。

如果你想在AssociatedObject_MouseLeftButtonUp事件處理程序中分離它,只要你真的不需要對它做更多的事情,你可以在方法的結尾調用detach。

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() 
} 

我絕對不會打電話給GC,這會對性能產生巨大影響。

+4

我認爲這是他所做的一點。當視圖從視覺樹中移除時,Silverlight應該調用'Detach'。 – 2012-01-09 10:39:48