我正在创建包含多个部分的自定义控件。在模板创建中,我正在订阅不同的事件,如下所示:
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();
}
所以,我想知道我是否应该取消订阅这些活动,如果是的话 - 在哪里以及如何?
答案 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
}
是的我知道这看起来有点矫枉过正,但是代码是样板文件,我们使用区域来汇总重复的东西,这样我们就可以检查实际做了一些有趣的代码,而不用担心管道问题。通过这一个实例,它很容易将其推广到多个部分。