2011-02-10 13 views
5

Ho creato un comportamento personalizzato (senza blend) per trascinare UIElements e ottenere una miniatura traslucida di ciò che stai trascinando sotto il cursore (la versione blends sposta l'oggetto target che non è quello che Ho bisogno)Silverlight Behavior onDetaching override non viene chiamato

Anyhoo, il codice è in realtà molto semplice e funziona bene, il problema che sto avendo è che onDetaching() non viene chiamato, il che significa che i miei eventi su UIElement non vengono sganciati.

Questo mi preoccupa un po 'perché sto indovinando l'unico motivo per cui il comportamento non è stato staccato perché è ancora riferito a qualcosa. Non dovrebbe essere l'UIElement, anche se abbiamo avuto problemi di perdita con esso in una fase, ma ora li abbiamo risolti e questo è stato chiarito tramite WinDbg.

L'unica cosa interessante (?) È che il comportamento è collegato a un'immagine in un controllo oggetti, ma questo non dovrebbe fare la differenza, giusto?

Ecco il mio codice corrente:

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

So di due posti che ho visto su questo ...

Questo - forums.silverlight.net/forums/p/142038/ 317146.aspx non aiuta perché ho provato a forzare un GC inutilmente, e questo - Automatically calling OnDetaching() for Silverlight Behaviors non ho davvero la loro esplosione mentre sostengono che il collegamento di UIElement al comportamento che lo causa, ma sicuramente quando il root reference UIElement è rotto, anche il riferimento root al comportamento verrà rimosso e, di conseguenza, entrambi saranno eleggibili per GC.

Speravo che sarebbe stato semplice, ma in caso contrario avrò iniziato con WinDbg per vedere cosa sta succedendo!

Qualsiasi aiuto è molto apprezzato! :)

Grazie,

Andy.

+1

Nessuno può aiutare? Immagino che proverò a postare nei forum silverlight! Aggiornerò questa discussione se dovessi arrivare da nessuna parte! – Andy

risposta

0

Non si mostra da dove viene chiamato il Detach. Qualcosa deve effettivamente chiamare l'oggetto.Detach() (DragBehavior) per chiamare il metodo OnDetaching().

Se si desidera scollegarlo nel gestore di eventi AssociatedObject_MouseLeftButtonUp, è possibile richiamare lo scollegamento alla fine del metodo, purché non sia necessario eseguire di più.

Definitivamente, non avrei effettuato chiamate a GC che possono avere un impatto enorme sulle prestazioni.

+4

Penso che sia il punto che sta facendo. Silverlight dovrebbe chiamare "Scollega" quando la vista viene rimossa dall'albero visivo. –

Problemi correlati