WPF TemplateParts


Pokud se potřebujete dostat na vnitřní a skryté části systémových ovládacích prvků nebo vlastních controlů, vhodným řešení je využít systém “TemplateParts”…

Napadají mě především dva hlavní scénáře využití…

1) Přístup k vnitřním nebo skrytým částem již existujících, resp. systémových ovládacích prvků:

Vytvářím vlastní DatePicker, který dědí od toho systémového a chci v kódu přistupovat k jeho části s názvem “PART_TextBox”, o které vím, protože jsem si kód systémového DatePicker disassembloval a prošel např. pomocí dotPeek a buď můžu použít načtení pomocí Template.FindName(“Název”) anebo GetTemplateChild(“Název”) a přístup přes property, či přepsání události, resp. rodičovské metody OnApplyTemplate…


public class MyDatePicker1 : DatePicker
{
  public const string TextBoxPartName = "PART_TextBox";
  private DatePickerTextBox m_TextBoxPart;


  internal DatePickerTextBox TextBoxPart
  {
    get
    {
      if (m_TextBoxPart == null && IsLoaded)
      {
        m_TextBoxPart = Template.FindName(TextBoxPartName, this) as DatePickerTextBox;
        // todo: vlastní inicializace
      }
      return m_TextBoxPart;
    }
  }
}

[TemplatePart(Name = TextBoxPartName, Type = typeof(DatePickerTextBox))]
public class MyDatePicker2 : DatePicker
{
  public const string TextBoxPartName = "PART_TextBox";


  private DatePickerTextBox TextBoxPart { get; set; }


  public override void OnApplyTemplate()
  {
    base.OnApplyTemplate();

    TextBoxPart = GetTemplateChild(TextBoxPartName) as DatePickerTextBox;
    if (TextBoxPart != null)
    {
      // todo: vlastní inicializace
    }
  }
}

Řešení MyDatePicker2 mi osobně přijde čistější a navíc se to stejným způsobem používá právě v systémových controlech. Akorát je nutné si dát pozor na to, že nejprve probíhá inicilizace Dependency Properties apod., dále událost (On)Intialized, pak až (On)ApplyTemplate a pak ještě pro úplnost (On)Loaded. Stejný sled událostí samozřejmě platí i pro první přístup přes property, takže v případě přístupu ještě před provedením OnApplyTemplate je nutné ošetřit  případné kontroly na null a pak pozdější správnou inicializaci apod.

2) Doplnění systémových, resp. vlastních ovládacích prvků o nové části:

Když bych dále můj vlastní DatePicker rozšiřoval i vlastní (Control)Template, tak bych v kódu postupoval stejným způsobem jako bylo naznačeno výše. Takže by stačilo si vypůjčit vzorový Template z MSDN (kde je definován i seznam částí, takže ani není potřeba používat dekompilaci) a v XAMLu už si upravit, či doplnit svou vlastní část kódu, resp. ovládací prvky.

, , ,

Komentáře jsou uzavřeny.