Laden...

Warum funktioniert das TemplateBinding in meinem ControlTemplate nicht?

Erstellt von Astrix vor 11 Jahren Letzter Beitrag vor 11 Jahren 3.692 Views
A
Astrix Themenstarter:in
12 Beiträge seit 2012
vor 11 Jahren
Warum funktioniert das TemplateBinding in meinem ControlTemplate nicht?

Hi,

ich habe in einer WPF-Anwendugn eine Klasse "ButtonModern" die von "Button" ableitet.

In dieser Klasse erweitere ich die Basisklasse "Button" u.a. um eine DependencyProperty "IconScale".

Den Wert aus "IconScale" möchte ich in einer RenderTransform des ContentPresenters in meinem Style verwenden und dachte zunächst ich könnte einfach mit TemplateBinding auf den Wert meiner Property zugreifen. Dies habe ich so gemacht:


    <Style TargetType="Controls:ButtonModern">
       <Setter Property="IconScale" Value="0.1" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Controls:ButtonModern">
                    <Grid Background="{TemplateBinding Property=Background}">
                        <Grid Margin="8">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="False" RenderTransformOrigin="0.5,0.5">
                                <ContentPresenter.Effect>
                                    <DropShadowEffect Opacity="0.5"/>
                                </ContentPresenter.Effect>
                                <ContentPresenter.RenderTransform>
                                   <ScaleTransform ScaleX="{TemplateBinding Property=IconScale}" ScaleY="{TemplateBinding Property=IconScale}"/>        
                        </ContentPresenter.RenderTransform>
                            </ContentPresenter>
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Allerdings scheint das TemplateBinding in diesem Fall nicht zu funktionieren, da die Scale immer "1" ist.

Wende ich hingegen ein Binding mit RelativeSource TemplatedParent an funktioniert es:


    <Style TargetType="Controls:ButtonModern">
       <Setter Property="IconScale" Value="0.1" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Controls:ButtonModern">
                    <Grid Background="{TemplateBinding Property=Background}">
                        <Grid Margin="8">
                            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" RecognizesAccessKey="False" RenderTransformOrigin="0.5,0.5">
                                <ContentPresenter.Effect>
                                    <DropShadowEffect Opacity="0.5"/>
                                </ContentPresenter.Effect>
                                <ContentPresenter.RenderTransform>
                                    <ScaleTransform ScaleX="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IconScale}" ScaleY="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IconScale}"/>   
                             </ContentPresenter.RenderTransform>
                            </ContentPresenter>
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Meine Frage ist nun warum die Variante mit dem TemplateBinding nicht funktioniert? Ich meine, bei dem umschließenden Grid funktioniert das TemplateBinding für den Background ja schließlich auch?

EDIT: was mir eben noch aufgefallen ist: obwohl das Beispiel 2 funktioniert, meldet Visual Studio beim Starten im Direktfenster den folgenden Fehler:
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=IconScale; DataItem=null; target element is 'ScaleTransform' (HashCode=13842929); target property is 'ScaleX' (type 'Double')

Vielen Dank für alle Antworten im voraus,
Astrix

582 Beiträge seit 2008
vor 11 Jahren

Kann es sein, dass du IconScale nicht korrekt initialisierst? Wenn du IconScale mit null initialisert, dann kann es zu so einer Fehlermeldung kommen. Dürfte aber nicht deinen Problem erklären.

Gruß dat Tala

M
171 Beiträge seit 2012
vor 11 Jahren

Hallo Astrix,

ich bin jetzt auch noch relativ neu bei WPF, aber ich vermute mal, dass das TemplateBinding sich immer auf das unmittelbare Element bezieht, in dem es verwendet wird.

In Deinem Fall würde sich das TemplateBinding dann auf ein (nicht vorhandenes) Template für einen ContentPresenter beziehen. Aber da wird sich sicher noch jemand hier finden, der das sicherer erklären kann.

1.378 Beiträge seit 2006
vor 11 Jahren

Hier hab ich einen interessanten Thread dazu gefunden: WPF TemplateBinding vs RelativeSource TemplatedParent

Speziell diese Erklärung dazu gefällt mir:

TemplateBinding - More limiting than using regular Binding

More efficient than a Binding but it has less functionality  
Only works inside a ControlTemplate&#39;s visual tree  
**Doesn&#39;t work with properties on Freezables**  
Doesn&#39;t work within a ControlTemplate&#39;s Trigger  
Provides a shortcut in setting properties(not as verbose),e.g. {TemplateBinding targetProperty}  

Regular Binding - Does not have above limitations of TemplateBinding

Respects Parent Properties  
Resets Target Values to clear out any explicitly set values  
Example: &lt;Ellipse Fill=&quot;{Binding RelativeSource={RelativeSource TemplatedParent},Path=Background}&quot;/&gt;