2011-11-01 38 views
1

我正在创建包含多个零件的自定义控件。里面创建模板,我订阅了不同的事件,像这样:何时取消订阅自定义控件中的事件

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

所以,我不知道是否应该从这些事件中,如果是取消 - 在哪里以及如何?

回答

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 
} 

是的,我知道这看起来有点小题大做,但代码是样板,我们使用地区汇总的东西,周反复,所以我们可以检查代码实际执行一些有趣的事情,而不关心管道。有了这个例子,它很容易推出到多个部分。

+0

太好了。我希望我可以发布我的代码,让有知识的人阅读它:)这是我的第一个控制 – katit

+0

+1没有想到这一点。如果您要更改模板,则不想在存储器中保留未使用的PART元素。 – dowhilefor

2

你不需要。因为你的PART元素是事件订阅者的子项。如果你的主控制器收集垃圾,你的PART元素也是如此。 一个简短的例子。假设你有2个实例A和B ... A保持对B的硬引用。如果B只在A的引用中保存在内存中,并且A获取垃圾回收,那么B也是如此。你不需要清除引用在第一。

如果由于某种原因,当你的元素和你的PART子元素一起生活时,你不再需要事件,当然你不得不放弃。

经验法则:如果事件所有者的寿命长于用户,则总是取消订阅事件。

相关问题