WPF – TemplateBinding i TemplatedParent a wyzwalacze w szablonie kontrolki

2013-01-26

Niedawno tworząc szablon kontrolki w WPF natknąłem się na pewien problem. Chcąc odwołać się z szablonu do właściwości kontrolki standardowo użyłem rozszerzenia TemplateBinding. Kod się skompilował ale po uruchomieniu aplikacji pojawił się wyjątek. Oto uproszczona postać szablonu:

<ControlTemplate x:Key="buttonTemplate" TargetType="Button">
    <Border Name="border"
            Background="{TemplateBinding Background}">
        <ContentPresenter Name="content"
                          HorizontalAlignment="Center"
                          VerticalAlignment="Center" />
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter TargetName="border"
                    Property="Background"
                    Value="{TemplateBinding Foreground}" />
            <Setter TargetName="content"
                    Property="TextBlock.Foreground"
                    Value="{TemplateBinding Background}" />
        </Trigger>
        <Trigger Property="IsPressed" Value="True">
            <Setter TargetName="content"
                    Property="RenderTransform">
                <Setter.Value>
                    <TranslateTransform X="1" Y="1" />
                </Setter.Value>
            </Setter>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

Poniżej błąd jaki pojawił się po uruchomieniu aplikacji:

TemplateBinding

Wielokrotnie stosowałem TemplateBinding w szablonach więc ten błąd trochę mnie zdziwił. Po krótkich poszukiwaniach okazało się, że faktycznie używałem go wcześniej ale nigdy wewnątrz wyzwalacza. TemplateBinding jest skróconą formą wiązania zdefiniowanego w następujący sposób: {Binding RelativeSource={RelativeSource TemplatedParent}}. Jak się jednak okazało, oprócz skróconego zapisu posiada on również pewne ograniczenia. Jednym z nich jest brak możliwości stosowania go w wyzwalaczach. Po zmianie szablonu kontrolki polegającej na zastąpieniu rozszerzenia TemplateBinding wiązaniem do TemplatedParent w wyzwalaczach, wszystko działa zgodnie z oczekiwaniami:

<ControlTemplate x:Key="buttonTemplate" TargetType="Button">
    <Border x:Name="border"
            Background="{TemplateBinding Background}">
        <ContentPresenter x:Name="content"
                          HorizontalAlignment="Center"
                          VerticalAlignment="Center" />
    </Border>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter TargetName="border"
                    Property="Background"
                    Value="{Binding Foreground,
                                    RelativeSource={RelativeSource TemplatedParent}}" />
            <Setter TargetName="content"
                    Property="TextBlock.Foreground"
                    Value="{Binding Background,
                                    RelativeSource={RelativeSource TemplatedParent}}" />
        </Trigger>
        <Trigger Property="IsPressed" Value="True">
            <Setter TargetName="content"
                    Property="RenderTransform">
                <Setter.Value>
                    <TranslateTransform X="1" Y="1" />
                </Setter.Value>
            </Setter>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
Reklamy

Posted on 2013-01-26, in .NET/C# and tagged , , , , , . Bookmark the permalink. Dodaj komentarz.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

%d blogerów lubi to: