WPF TemplateBinding a RelativeSource TemplatedParent

169

Jaka jest różnica między tymi dwoma wiązaniami:

<ControlTemplate TargetType="{x:Type Button}">
   <Border BorderBrush="{TemplateBinding Property=Background}">
      <ContentPresenter />
   </Border>
</ControlTemplate>

i

<ControlTemplate TargetType="{x:Type Button}">
   <Border BorderBrush="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}">
      <ContentPresenter />
   </Border>
</ControlTemplate>

?

PaN1C_Showt1Me
źródło
17
jeśli potrzebujesz TwoWay Binding, musisz skorzystać z drugiej opcji
Joachim Kerschbaumer

Odpowiedzi:

207

TemplateBinding to nie to samo. Dokumenty MSDN są często pisane przez ludzi, którzy muszą sprawdzać monosylabowe SDE dotyczące funkcji oprogramowania, więc niuanse nie są do końca poprawne.

TemplateBindings są oceniane w czasie kompilacji względem typu określonego w szablonie kontrolnym. Pozwala to na znacznie szybsze tworzenie instancji skompilowanych szablonów. Po prostu znajdź nazwę w powiązaniu szablonu, a zobaczysz, że kompilator oznaczy ją flagą.

Znacznik powiązania jest rozpoznawany w czasie wykonywania. Chociaż wolniejsze do wykonania, powiązanie rozwiąże nazwy właściwości, które nie są widoczne w typie zadeklarowanym przez szablon. Wolniej wskażę, że jest to rodzaj względny, ponieważ operacja wiązania zajmuje bardzo mało procesora aplikacji. Jeśli strzelałeś z szablonów kontrolnych z dużą prędkością, możesz to zauważyć.

W ramach praktyki używaj TemplateBinding, kiedy możesz, ale nie obawiaj się Binding.

Grant BlahaErath
źródło
18
Więc główna myśl do zapamiętania: czas kompilacji a środowisko wykonawcze. TemplateBinding nie zadziała, jeśli spróbujesz go zmienić w czasie wykonywania. Dobrze ?
PaN1C_Showt1Me
3
Należy również zauważyć, że użycie Binding zamiast TemplateBinding może mieć wpływ na to, co widać w czasie projektowania. W niektórych konfiguracjach właściwości, które są powiązane przy użyciu {Binding RelativeSource ...} nie pojawią się w projektancie (chociaż nadal pojawiają się w czasie wykonywania), ale jeśli przełączysz się na używanie {TemplateBinding ...}, te właściwości są oceniane w czasie projektowania.
lfalin
Jedną rzeczą, którą dodam na wypadek, gdyby pomagało to przyszłym odwiedzającym, jest to, że ponieważ TemplateBinding jest oceniany w czasie kompilacji, nie można użyć TemplateBinding do powiązania z dołączoną właściwością zdefiniowaną przez użytkownika. W przypadku dołączonych właściwości zdefiniowanych przez użytkownika należy użyć „{Binding RelativeSource = {RelativeSource TemplatedParent} ...}”
MNB
35

TemplateBinding - bardziej ograniczające niż używanie zwykłego Binding

  • Bardziej wydajne niż powiązanie, ale ma mniejszą funkcjonalność
  • Działa tylko w drzewie wizualnym ControlTemplate
  • Nie działa z właściwościami Freezables
  • Nie działa w wyzwalaczu ControlTemplate
  • Zapewnia skrót do ustawiania właściwości (nie jako gadatliwy), np. {TemplateBinding targetProperty}

Zwykłe wiązanie - nie ma powyższych ograniczeń TemplateBinding

  • Szanuje właściwości nadrzędne
  • Resetuje wartości docelowe, aby usunąć wszelkie jawnie ustawione wartości
  • Przykład: <Ellipse Fill = "{Binding RelativeSource = {RelativeSource TemplatedParent}, Path = Background}" />
Paul Fischer
źródło
22

Jeszcze jedno - TemplateBindings nie pozwalają na konwersję wartości. Nie pozwalają na przekazanie konwertera i nie konwertują na przykład automatycznie int na string (co jest normalne dla Binding).

Miroslav Nedyalkov
źródło
1
Dzięki Miroslav, to był problem, który napotkałem, przejście do korzystania z TemplatedParent rozwiązało problem.
MikeKulls
17

TemplateBinding to skrót dla Binding with TemplatedParent, ale nie ujawnia wszystkich możliwości klasy Binding, na przykład nie można kontrolować Binding.Mode z TemplateBinding.

Nir
źródło
1

Myślałem, że TemplateBinding nie obsługuje typów Freezable (w tym obiektów pędzla). Aby obejść problem. Można skorzystać z TemplatedParent

Yaz
źródło