Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use an ElementName binding within a ControlTemplate?

I have multiple TextBlocks which reference different elements in my application. My code works fine when used directly in the page. However, I want to create a ControlTemplate and a ContentControl to reduce the duplication of code.

How can I pass a reference to an ElementName into the ControlTemplate from the ContentControl using TemplateBinding? The following code throws this error:

"Cannot convert the value in attribute 'ElementName' to object of type 'System.String'. Object of type 'System.Windows.TemplateBindingExpression' cannot be converted to type 'System.String'. "

In addition to the Tag attribute, I have tried ContentStringFormat which also did not work.

What is the correct method to get this to work using templates?

Thanks in advance for your help,

--- Shawn

Here is the code sample:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <Page.Resources>
        <ControlTemplate x:Key="MyTemplate" TargetType="{x:Type ContentControl}">
            <TextBlock Margin="{Binding ElementName={TemplateBinding Tag}, Path=Margin}" Text="{TemplateBinding Content}" TextAlignment="{Binding ElementName={TemplateBinding Tag}, Path=TextAlignment}" Width="{Binding ElementName={TemplateBinding Tag}, Path=Width}" />
        </ControlTemplate>
    </Page.Resources>
    <StackPanel>
        <TextBlock x:Name="AnotherElement" Margin="10" Text="Main TextBlock" TextAlignment="Center" Width="100" />
        <TextBlock x:Name="AnotherElement2" Margin="20" Text="Second TextBlock" TextAlignment="Left" Width="250" />
        <TextBlock Margin="{Binding ElementName=AnotherElement, Path=Margin}" Text="Here is my TextBlock!" TextAlignment="{Binding ElementName=AnotherElement, Path=TextAlignment}" TextTrimming="CharacterEllipsis" Width="{Binding ElementName=AnotherElement, Path=Width}" />
        <TextBlock Margin="{Binding ElementName=AnotherElement2, Path=Margin}" Text="Here is my Second TextBlock!" TextAlignment="{Binding ElementName=AnotherElement2, Path=TextAlignment}" TextTrimming="CharacterEllipsis" Width="{Binding ElementName=AnotherElement2, Path=Width}" />
        <ContentControl Content="Hello!" Tag="AnotherElement" Template="{StaticResource MyTemplate}" />
        <ContentControl Content="Hello Again!" Tag="AnotherElement2" Template="{StaticResource MyTemplate}" />
    </StackPanel>
</Page>
like image 464
Shawn Roser Avatar asked Mar 07 '13 22:03

Shawn Roser


1 Answers

This seems like a funny way to template something, but it can be done, you just have to get a bit fancy with your bindings.

The below will work, but I still dont think this is a good way to template a control

Bind the TextBlock Tag to the actual Element, then in the ControlTemplate bind Tag to Tag and use the values from there as Tag is the Element, you can use any element from it.

<Page.Resources>
    <ControlTemplate x:Key="MyTemplate" TargetType="{x:Type ContentControl}">
        <TextBlock Name="_this" Tag="{TemplateBinding Tag}" Margin="{Binding ElementName=_this, Path=Tag.Margin}" Text="{TemplateBinding Content}" TextAlignment="{Binding ElementName=_this, Path=Tag.TextAlignment}" Width="{Binding ElementName=_this, Path=Tag.Width}" />
    </ControlTemplate>
</Page.Resources>
<StackPanel>
    <TextBlock x:Name="AnotherElement" Margin="10" Text="Main TextBlock" TextAlignment="Center" Width="100" />
    <TextBlock x:Name="AnotherElement2" Margin="20" Text="Second TextBlock" TextAlignment="Left" Width="250" />
    <TextBlock Margin="{Binding ElementName=AnotherElement, Path=Margin}" Text="Here is my TextBlock!" TextAlignment="{Binding ElementName=AnotherElement, Path=TextAlignment}" TextTrimming="CharacterEllipsis" Width="{Binding ElementName=AnotherElement, Path=Width}" />
    <TextBlock Margin="{Binding ElementName=AnotherElement2, Path=Margin}" Text="Here is my Second TextBlock!" TextAlignment="{Binding ElementName=AnotherElement2, Path=TextAlignment}" TextTrimming="CharacterEllipsis" Width="{Binding ElementName=AnotherElement2, Path=Width}" />
    <ContentControl Content="Hello!" Tag="{Binding ElementName=AnotherElement}" Template="{StaticResource MyTemplate}" />
    <ContentControl Content="Hello Again!" Tag="{Binding ElementName=AnotherElement2}" Template="{StaticResource MyTemplate}" />
</StackPanel>
like image 134
sa_ddam213 Avatar answered Oct 17 '22 23:10

sa_ddam213