2011-02-10 7 views
5

UIElementsをドラッグし、カーソルの下にドラッグしているものの半透明のサムネイルを取得するためのブレンドなしのカスタムビヘイビアを作成しました(ブレンドバージョンは、私はonDetaching()が呼び出されていないということは、UIElementへの私のイベントがunhookedされていないことを意味している問題は、実際には非常にシンプルでうまく動作します。Silverlightの動作onDetachingのオーバーライドが呼び出されない

これは、動作が切り離されていない唯一の理由は、まだ何かによって参照されているためです。それはUIElementであってはいけません。しかし、我々は一段階でそれに漏れの問題があったが、我々は今解決しており、これはWinDbgを通して明らかにされている。

唯一興味深いのは、アイテムコントロール内の画像にビヘイビアが添付されていますが、これでは違いはありませんか? - forums.silverlight.net/forums/p/142038/私はこのことについて見てきた2本の支柱を知っている

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

...

この1:

は、ここに私の現在のコードです317146.aspxはGCを無駄にしようとしましたが、この1つを助けてくれません - Automatically calling OnDetaching() for Silverlight Behaviors UIElementをその動作に結び付ける確かにルート参照のUIElementが壊れているときは、その動作へのルート参照も削除され、結果として両方ともGCに適するようになります。

私はこれがシンプルであることを望んでいましたが、もしそうでなければ、実際に何が起こっているかを見るためにWinDbgを使い始めるでしょう!

ご協力いただきありがとうございます。 :)

ありがとう、

アンディ

+1

誰でも助けることができますか?私は銀色のフォーラムでポジティブな試みをしようと思います!私がどこにいてもこのスレッドを更新します! – Andy

答えて

0

デタッチがどこから呼び出されているかは表示されません。 OnDetaching()メソッドが呼び出されるためには、何か実際にオブジェクトを呼び出す必要があります.Detach()(DragBehavior)

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'を呼び出すはずです。 –

関連する問題