I have a simple control that extends the WPF TextBox control. The basic idea is to save space in the UI, by enabling the TextBox to display its own label inside it when it is empty.
I have declared one DependencyProperty called Label in it and have set the TextBox.Template property to a ControlTemplate. The ControlTemplate is the default Windows Aero XAML with the addition of a TextBlock placed behind the control that displays the value of the TextBox.Text property. Its Visibility property is bound with a Converter to be visible whenever the Text property is empty. (There’s a lot and mostly uninteresting, so please excuse the scrollbar).
<ControlTemplate x:Key="LabelTextBoxTemplate" TargetType="{x:Type TextBoxBase}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Aero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
<Aero:ListBoxChrome Background="{TemplateBinding Panel.Background}" BorderBrush="{TemplateBinding Border.BorderBrush}" BorderThickness="{TemplateBinding Border.BorderThickness}" RenderMouseOver="{TemplateBinding UIElement.IsMouseOver}" RenderFocused="{TemplateBinding UIElement.IsKeyboardFocusWithin}" Name="Border" SnapsToDevicePixels="True">
<Grid>
<TextBlock Text="{Binding Label, ElementName=This}" Visibility="{Binding Text, ElementName=This, Converter={StaticResource StringToVisibilityConverter}}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" FontWeight="Normal" FontStyle="Italic" Foreground="#99000000" Padding="3,0,0,0" />
<ScrollViewer Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</Grid>
</Aero:ListBoxChrome>
<ControlTemplate.Triggers>
<Trigger Property="UIElement.IsEnabled" Value="False">
<Setter TargetName="Border" Property="Panel.Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
<Setter Property="TextElement.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
(The Name property of the control is set to This for the binding)
So anyway, this all works nicely but I was wondering if I could replace this functionality with an Attached Property. I created an Attached Property called Label and added a callback delegate that gets called when the property is set. In this method, I planned to find the ControlTemplate from the Application.Resources and set the TextBox.Template property to it… I couldn’t find a way to access the ControlTemplate so this is my first question.
How can I access a ControlTemplate in the Application.Resources in App.xaml from an Attached Property?
The rest of the question is how can I then bind to the Attached Property in the ‘ControlTemplate’?
I have tried several things like
Text="{Binding Path=(Attached:TextBoxProperties.Label),
Source={x:Static Attached:TextBoxProperties}, FallbackValue=''}"
but the TextBoxProperties class that contains the Attached Property is not static.
UPDATE >>>
Thanks to H.B. I found that I could access the ControlTemplate using the following code.
ControlTemplate labelControlTemplate =
(ControlTemplate)Application.Current.FindResource("LabelTextBoxTemplate");
You should be able to access the
Application.Resourcesfrom:Application.Current.Resources.The binding should probably be this:
It should not matter if the class containing the property is static, the bindng engine will see whether the property is set on the
TextBox, it does not care about the declaring class.