Button ControlTemplate Exception: Element is already loaded
Hey all, I'm slowly figuring out xaml and ran into an issue that I'm a bit stumped on. I've got a button control template that I wanted to add text drop shadow for, however I get the exception that the element is already loaded when I add a second ContentPresenter to the template, here's the code that works and below the code that doesn't. Any info would be greatly appreciated, and for reference I was following the info found here: http://mark-dot-net.blogspot.com/2007/0 ... te-in.html
Code: Select all
<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>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="GUIResources/ArtTextureAtlas.xaml"/>
<ResourceDictionary Source="GUIResources/IconsTextureAtlas.xaml"/>
<ResourceDictionary Source="GUIResources/InteractTextureAtlas.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="ShadowStyle">
<Setter Property="Control.Foreground" Value="LightGray" />
</Style>
<Style x:Key="InformButton" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="FontFamily" Value="GUIFonts/#JandaAmazingGrace"/>
<Setter Property="FontSize" Value="11px"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="Border" Background="{DynamicResource Btn_Cache_Internl_neutral}">
<Grid>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="content"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource Btn_Cache_Internl_over}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource Btn_Cache_Internl_down}" />
<Setter TargetName="content" Property="RenderTransform" >
<Setter.Value>
<TranslateTransform Y="1.0" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsDefaulted" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource Btn_Cache_Internl_over}" />
</Trigger>
<Trigger Property="IsFocused" Value="True" />
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource Btn_Cache_Internl_inactive}" />
<Setter Property="Foreground" Value="Gray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Page.Resources>
<StackPanel HorizontalAlignment="Center">
<Button Style="{StaticResource InformButton}" Width="225" Height="63">Hello</Button>
<Button Style="{StaticResource InformButton}">World</Button>
<Button Style="{StaticResource InformButton}" FontSize="20">Big Button</Button>
<Button Style="{StaticResource InformButton}" IsDefault="True">Default</Button>
<Button Style="{StaticResource InformButton}" IsEnabled="False">Disabled</Button>
<Button Style="{StaticResource InformButton}" Width="70" Height="30">70 x 30</Button>
<TextBox />
<Button Style="{StaticResource InformButton}" Width="30" Height="30">
<Path Fill="Black" Data="M 3,3 l 9,9 l -9,9 Z" />
</Button>
<Button Width="70" Height="30">70 x 30</Button>
</StackPanel>
</Page>
Code: Select all
<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>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="GUIResources/ArtTextureAtlas.xaml"/>
<ResourceDictionary Source="GUIResources/IconsTextureAtlas.xaml"/>
<ResourceDictionary Source="GUIResources/InteractTextureAtlas.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="ShadowStyle">
<Setter Property="Control.Foreground" Value="LightGray" />
</Style>
<Style x:Key="InformButton" TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="FontFamily" Value="GUIFonts/#JandaAmazingGrace"/>
<Setter Property="FontSize" Value="11px"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="Border" Background="{DynamicResource Btn_Cache_Internl_neutral}">
<Grid>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="contentShadow" Style="{StaticResource ShadowStyle}">
<ContentPresenter.RenderTransform>
<TranslateTransform X="1.0" Y="1.0" />
</ContentPresenter.RenderTransform>
</ContentPresenter>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Name="content"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource Btn_Cache_Internl_over}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource Btn_Cache_Internl_down}" />
<Setter TargetName="content" Property="RenderTransform" >
<Setter.Value>
<TranslateTransform Y="1.0" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsDefaulted" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource Btn_Cache_Internl_over}" />
</Trigger>
<Trigger Property="IsFocused" Value="True" />
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource Btn_Cache_Internl_inactive}" />
<Setter Property="Foreground" Value="Gray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Page.Resources>
<StackPanel HorizontalAlignment="Center">
<Button Style="{StaticResource InformButton}" Width="225" Height="63">Hello</Button>
<Button Style="{StaticResource InformButton}">World</Button>
<Button Style="{StaticResource InformButton}" FontSize="20">Big Button</Button>
<Button Style="{StaticResource InformButton}" IsDefault="True">Default</Button>
<Button Style="{StaticResource InformButton}" IsEnabled="False">Disabled</Button>
<Button Style="{StaticResource InformButton}" Width="70" Height="30">70 x 30</Button>
<TextBox />
<Button Style="{StaticResource InformButton}" Width="30" Height="30">
<Path Fill="Black" Data="M 3,3 l 9,9 l -9,9 Z" />
</Button>
<Button Width="70" Height="30">70 x 30</Button>
</StackPanel>
</Page>
-
-
sfernandez
Site Admin
- Posts: 3197
- Joined:
Re: Button ControlTemplate Exception: Element is already loa
You can't have 2 ContentPresenter inside the same template because Content would be assigned to both, and a Visual element can only have 1 visual parent.
You have two options:
A) Use a binding to create the shadow TextBlock
B) Create the shadow text as part of the button content
I think method A is more convenient, although it only works if you set Button.Content as a string.
You have two options:
A) Use a binding to create the shadow TextBlock
B) Create the shadow text as part of the button content
Code: Select all
<Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid.Resources>
<ControlTemplate x:Key="ButtonTemplate1" TargetType="Button">
<Border Background="Silver" Padding="4,2">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="{TemplateBinding Content}" Foreground="White" Margin="1,1,-1,-1"/>
<ContentPresenter/>
</Grid>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="ButtonTemplate2" TargetType="Button">
<Border Background="Silver" Padding="4,2">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Grid.Resources>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Content="This is a Button" Template="{StaticResource ButtonTemplate1}" Foreground="Black" Margin="2"/>
<Button Template="{StaticResource ButtonTemplate2}" Margin="2">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="{Binding Text, ElementName=txt}" Foreground="White" Margin="1,1,-1,-1"/>
<TextBlock x:Name="txt" Text="This is a Button" Foreground="Black"/>
</Grid>
</Button>
</StackPanel>
</Grid>
Re: Button ControlTemplate Exception: Element is already loa
Awesome, that also answers a lot of other questions I had floating about on the whole template stuff. Though I can only assume that this works in Blend, but not NoesisGUI / Unity because of the WPF version I'm targeting or is this just one of those differences between WPF's implementation and Noesis' implementation?
-
-
sfernandez
Site Admin
- Posts: 3197
- Joined:
Re: Button ControlTemplate Exception: Element is already loa
[An extension of my previous answer:]
I just realize you can even use 2 ContentPresenter in your template while the Button Content is a string:
You would get an error message only when Button Content is specified as any UI element (a TextBlock for example), because as I explained in the previous answer, a Visual can only have 1 Visual parent.
I just realize you can even use 2 ContentPresenter in your template while the Button Content is a string:
Code: Select all
<ControlTemplate x:Key="ButtonTemplate0" TargetType="Button">
<Border Background="Silver" Padding="4,2">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<ContentPresenter TextElement.Foreground="White" Margin="1,1,-1,-1"/>
<ContentPresenter/>
</Grid>
</Border>
</ControlTemplate>
Code: Select all
<Button
Content="This is a Button"
Template="{StaticResource ButtonTemplate0}"
Foreground="Black"
Margin="2"/>
-
-
sfernandez
Site Admin
- Posts: 3197
- Joined:
Re: Button ControlTemplate Exception: Element is already loa
The behavior of NoesisGUI should be the same as in WPF/Blend, if that is not the case, we have a bug and we have to fix it.Awesome, that also answers a lot of other questions I had floating about on the whole template stuff. Though I can only assume that this works in Blend, but not NoesisGUI / Unity because of the WPF version I'm targeting or is this just one of those differences between WPF's implementation and Noesis' implementation?
I will make some tests and let you know.
Re: Button ControlTemplate Exception: Element is already loa
May be related to the templating issue in: viewtopic.php?f=3&t=316
Similar situation, in that it worked in Blend.
Similar situation, in that it worked in Blend.
-
-
sfernandez
Site Admin
- Posts: 3197
- Joined:
Re: Button ControlTemplate Exception: Element is already loa
You were right, ContentPresenter was not behaving exactly the same in Blend and in NoesisGUI. I will fix the problem for the next release, so your xaml could load correctly.Awesome, that also answers a lot of other questions I had floating about on the whole template stuff. Though I can only assume that this works in Blend, but not NoesisGUI / Unity because of the WPF version I'm targeting or is this just one of those differences between WPF's implementation and Noesis' implementation?
Who is online
Users browsing this forum: Ahrefs [Bot] and 12 guests