Когда мне отписаться от событий внутри пользовательского элемента управления

#c# #silverlight

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

Итак, мне интересно, должен ли я отписаться от этих событий, и если да, то где и как?

Ответ №1:

Вам не обязательно. Потому что ваши элементы PART являются дочерними элементами подписчика события. Если ваш основной элемент управления собирает мусор, то и ваши элементы PART . Короткий пример. Допустим, у вас есть 2 экземпляра A и B… A сохраняет жесткую ссылку на B. Если B хранится в памяти только по ссылке в A, а A собирает мусор, то и B. Вам не нужно сначала очищать ссылку.

Если по какой-то причине вам больше не нужны события, пока ваш элемент с дочерними элементами вашей ЧАСТИ живет, вы, конечно, должны отказаться от подписки.

Эмпирическое правило: всегда отписывайтесь от событий, если владелец события живет дольше, чем подписчик.

Ответ №2:

Ну, вы уже приняли ответ, и, возможно, вам удастся отказаться от этого подхода, но на мой вкус это слишком рискованно. Предполагается, что 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
}
 

Да, я знаю, что это выглядит как перебор, но код является шаблонным, и мы используем регионы для свертки повторяющегося материала, чтобы мы могли проверять код, который на самом деле делает что-то интересное, не заботясь о сантехнике. С помощью этого одного экземпляра его легко развернуть на несколько частей.

Комментарии:

1. Отлично. Хотелось бы, чтобы я мог просто опубликовать свой код, чтобы кто-нибудь знающий его просмотрел 🙂 Это мой первый элемент управления

2. 1 Не думал об этом. Если вы собираетесь изменить шаблон, вы не хотите хранить неиспользуемые элементы ДЕТАЛИ в памяти.

3. @dowhilefor ну и что? Подписка на событие элемента ДЕТАЛИ заставит его содержать ссылку на элемент управления, а не наоборот. Итак, если шаблон изменен — элементы все равно будут собраны.