Reputation: 17915
I'm creating custom control that contain multiple parts. Inside template creation I'm subscribing for different events like so:
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();
}
So, I wonder if I should unsubscribe from those events and if so - where and how?
Upvotes: 1
Views: 994
Reputation: 189457
Well you've accepted an answer already and you may be able to get away that approach but its a too risky for my tastes. It assumes that OnApplyTemplate
only ever gets called once. Potentially though your custom control may live a long time with OnApplyTemplate
getting called more than once.
I'll outline here what hard-core control developers do, I'll just use one TextBox
for brevity.
[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
}
Yes I know that this looks like overkill but the code is boilerplate and we use regions to rollup the repeative stuff so we can inspect code that actually does something interesting without being concerned with the plumbing. With this one instance its easy to roll it out to multiple parts.
Upvotes: 3
Reputation: 11051
You don't have to. Because your PART elements are children of the event subscriber. If your main control gets garbage collected, so do your PART elements. A short example. Lets say you have 2 instances A and B ... A keeps a hard reference to B. If B is only hold in memory by the reference in A and A gets garbage collected so does B. You don't need to clear the reference in A first.
If for some reason you don't want events anymore while your element, with your PART child elements, lives you have to unsubsribe of course.
A Rule of thumb: Always unsubscribe events if the event owner lives longer than the subscriber.
Upvotes: 4