【问题标题】:Silverlight Behaviour onDetaching override not being called未调用 Silverlight 行为 onDetaching 覆盖
【发布时间】:2011-06-24 19:12:37
【问题描述】:

我创建了一个自定义行为(没有混合),用于拖动 UIElements 并获取您在光标下拖动的内容的半透明缩略图(混合版本移动了我不需要的目标对象)

无论如何,代码实际上非常简单并且运行良好,我遇到的问题是 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 的条件。

我希望这很简单,但如果不是,我将开始使用 WinDbg 看看实际发生了什么!

非常感谢任何帮助! :)

谢谢,

安迪。

【问题讨论】:

  • 没有人可以帮忙吗?猜猜我会尝试在silverlight论坛上发帖!如果我有任何地方,我会更新这个帖子!

标签: c# silverlight events memory-leaks behavior


【解决方案1】:

您没有显示从哪里调用 Detach。需要实际调用 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 进行任何调用。

【讨论】:

  • 我认为这就是他的意思。当视图从可视化树中移除时,Silverlight 应该调用“分离”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多