Удаление обработчиков событий из частей шаблона пользовательского элемента управления - PullRequest
2 голосов
/ 15 июня 2011

Когда я впервые начал писать пользовательские элементы управления WPF, если я хотел добавить обработчик событий, я делал это в переопределении элемента управления OnApplyTemplate после получения части шаблона:

public void override OnApplyTemplate() {
  if ( addMenu != null ) {
    addMenu.Click -= addMenu_Click;
    addMenu = null;
  }
  addMenu = (MenuItem)Template.FindName("PART_AddMenu", this); 
  addMenu.Click += addMenu_Click;
}

Но затем однажды я заметил, что OnApplyTemplate () не всегда вызывается, когда я ожидаю, что это произойдет, то есть когда элемент управления отключен от визуального дерева. То есть, используя описанную выше технику, обработчики событий не всегда будут удалены. Поэтому я придумал другой способ:

public MyCustomControl()
{
  Loaded += this_Loaded;
}

void this_Loaded(object sender, RoutedEventArgs e)
{
  Unloaded += this_Unloaded;

  addMenu = (MenuItem)Template.FindName("PART_AddMenu", this);
  addMenu.Click += addMenu_Click;
}

void this_Unloaded(object sender, RoutedEventArgs e)
{
  Unloaded -= this_Unloaded;

  if (addMenu != null)
  {
    addMenu.Click -= addMenu_Click;
    addMenu = null;
  }
}

Этот способ, кажется, делает свое дело. Все согласны с тем, что это лучший способ подключения и удаления обработчиков событий в пользовательском элементе управления? Если нет, то почему?

Ответы [ 2 ]

2 голосов
/ 15 июня 2011

Этот метод хорош, но вы должны понимать, что иногда вы получаете событие unloaded, что вы не хотите, чтобы обработчики событий были отсоединены. Например, предположим, у вас есть элемент управления вкладкой. Когда вы переключаете TabItems, содержимое предыдущего TabItem все выгружается, а затем перезагружается, когда TabItem снова выбирается. Это хорошо для таких вещей, как Button.Click, потому что вы не можете выполнять такие действия на неактивной вкладке, но любые события, не требующие загрузки элемента в визуальное дерево, будут отключены, даже если элементы все еще существуют.

Почему вы чувствуете, что вам нужно очистить все обработчики событий? Я понимаю, что есть некоторые случаи, когда они могут зависать от ссылки на другой объект, но это необычный случай, и обычно лучше всего справиться с его очисткой при использовании таким образом. Вот несколько подробностей об этом: Как встроенные элементы управления WPF управляют своими обработчиками событий с прикрепленным событием?

0 голосов
/ 10 июня 2019

Элементы управления WPF (такие как ComboBox) используют метод OnTemplateChangedInternal() для отмены регистрации событий, зарегистрированных в OnApplyTemplate().Вы можете переопределить этот метод, так как он является внутренним по отношению к dll PresentationFramework, но вы можете переопределить защищенный метод OnTemplateChanged(), чтобы сделать то же самое - он вызывается OnTemplateChangedInternal() в базовом классе Control.

Вот пример кодаэто может войти в ваш пользовательский элемент управления:

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            EditableTextBoxSite = GetTemplateChild("PART_EditableTextBox") as TextBox;
            EditableTextBoxSite.TextChanged += new TextChangedEventHandler(this.OnEditableTextBoxTextChanged);
            this.EditableTextBoxSite.PreviewTextInput -= new TextCompositionEventHandler(this.OnEditableTextBoxPreviewTextInput);
        }

        protected override void OnTemplateChanged(ControlTemplate oldTemplate, ControlTemplate newTemplate)
        {
            base.OnTemplateChanged(oldTemplate, newTemplate);
            if (this.EditableTextBoxSite == null)
                return;
            this.EditableTextBoxSite.TextChanged -= new TextChangedEventHandler(this.OnEditableTextBoxTextChanged);
            this.EditableTextBoxSite.PreviewTextInput -= new TextCompositionEventHandler(this.OnEditableTextBoxPreviewTextInput);
        }

Я не уверен во всех последствиях этого, но, похоже, это самый близкий способ подражать тому, что делают элементы управления WPF.

...