2011-11-01 10 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 
} 

はい、私はこれはやり過ぎのように見えますが、コードが定型であり、我々は我々が実際に配管に関係せずに何か面白いものを行うコードを調べることができるようにrepeativeものをロールアップする領域を使用することを知っています。この1つのインスタンスを使用すると、複数の部分に簡単にロールアウトできます。

+0

私はちょうど私のコードを公開することができます誰かがそれを見直す知識:)それは私の最初のコントロールです – katit

+0

+1それを考えていない。テンプレートを変更する場合は、未使用のPART要素をメモリに保持したくない場合があります。 – dowhilefor

2

あなたはそうする必要はありません。あなたのPART要素はイベントサブスクライバの子であるためです。あなたのメインコントロールがガベージコレクションされた場合は、PART要素も同様に処理します。 短い例です。あなたが2つのインスタンスAとBを持っているとしましょう... AはBへのハードリファレンスを保持します.BがAのリファレンスによってメモリに保持され、Aがガベージコレクションを取得する場合B.同様にリファレンスをクリアする必要はありません最初にA。

何らかの理由で、PARTの子要素を持つ要素が生き残っている間にイベントをもう欲しくない場合は、もちろん退会する必要があります。

経験則:イベントの所有者がサブスクライバより長く生存している場合は、常にイベントを登録解除してください。

関連する問題