我何时取消订阅自定义控件中的事件

时间:2011-11-01 19:21:05

标签: c# silverlight

我正在创建包含多个部分的自定义控件。在模板创建中,我正在订阅不同的事件,如下所示:

public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.partAreaCode = this.GetTemplateChild(PartAreaCode) as TextBox;
            this.partExchange = this.GetTemplateChild(PartExchange) as TextBox;
            this.partSubscriber = this.GetTemplateChild(PartSubscriber) as TextBox;

            if (this.partAreaCode == null || this.partExchange == null || this.partSubscriber == null)
            {
                throw new NullReferenceException("Template part(s) not available");
            }

            this.partAreaCode.KeyDown += this.AreaKeyDown;
            this.partAreaCode.TextChanged += this.AreaTextChanged;

            this.partExchange.KeyDown += this.ExchangeKeyDown;
            this.partExchange.TextChanged += this.ExchangeTextChanged;

            this.partSubscriber.KeyDown += this.SubscriberKeyDown;

            // Template might be applied after dependency property set
            // lets refresh UI in this case
            this.UIFromValue();
        }

所以,我想知道我是否应该取消订阅这些活动,如果是的话 - 在哪里以及如何?

2 个答案:

答案 0 :(得分:4)

你不必。因为您的PART元素是事件订阅者的子元素。如果您的主控件被垃圾收集,那么您的PART元素也是如此。 一个简短的例子。假设您有2个实例A和B ... A保持对B的硬引用。如果B仅通过A中的引用保存在内存中,则A收集垃圾,B也是如此。您不需要清除引用在第一个。

如果由于某种原因你不想再发生任何事件,而你的元素与你的PART子元素一起生活,你当然必须取消订阅。

经验法则:如果活动所有者的寿命超过订阅者,则始终取消订阅活动。

答案 1 :(得分:3)

嗯,你已经接受了一个答案,你可能能够摆脱这种方法,但这对我的口味来说太冒险了。它假定OnApplyTemplate只被调用一次。虽然您的自定义控件可能会长时间活动OnApplyTemplate被多次调用。

我将在此概述核心控制开发人员的工作,为简洁起见,我只使用一个TextBox

[TemplatePart(Name = MyControl.PartAreaCode, Type = typeof(TextBox))]
public partial class MyControl: Control
{
     public MyControl()
     {
          DefaultStyleKey = typeof(MyControl);
     }

     #region Template Part Names
     private const string PartAreaCode = "AreaCodeTextBox";
     #endregion

     #region internal TextBox AreaCodeTextBox

     private TextBox _AreaCodeTextBox;
     internal TextBox AreaCodeTextBox
     {
          get { return _AreaCodeTextBox; }
          set
          {
              if (_AreaCodeTextBox != null)
              {
                   _AreaCodeTextBox -= AreaCodeTextBox_KeyDown;
                   _AreaCodeTextBox -= AreaCodeTextBox_TextChanged;
              }

              _AreaCodeTextBox = value;

              if (_AreaCodeTextBox != null)
              {
                   _AreaCodeTextBox += AreaCodeTextBox_KeyDown;
                   _AreaCodeTextBox += AreaCodeTextBox_TextChanged;
              }
          }
     }

     #endregion

     public overide void OnApplyTemplate()
     {
          base.OnApplyTemplate();
          AreaCodeTextBox = GetTemplateChild(PartAreaCode) as TextBox;
     }

     #region Part Event Handlers
     // Your event handlers here
     #endregion
}

是的我知道这看起来有点矫枉过正,但是代码是样板文件,我们使用区域来汇总重复的东西,这样我们就可以检查实际做了一些有趣的代码,而不用担心管道问题。通过这一个实例,它很容易将其推广到多个部分。