Reputation: 4040
I've made a custom window that has a template defined in a resource dictionary. The window has no title bar.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dsControls="clr-namespace:Something">
<Style x:Key="WindowRegionStyle"
TargetType="Window">
/** Other setters **/
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid>
<Border Background="{StaticResource WindowBackground}"
BorderBrush="{StaticResource BorderBrushColor}"
BorderThickness="1"
CornerRadius="8"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border CornerRadius="8,8,0,0"
BorderBrush="{StaticResource BorderBrushColor}"
Background="{StaticResource HeaderColor}"
Grid.ColumnSpan="2"
Grid.Row="0">
<Label Content="{Binding Path=(dsControls:WindowDetails.Title), RelativeSource={RelativeSource TemplatedParent}}"
FontSize="20" />
</Border>
<ContentPresenter Grid.Row="1" Grid.ColumnSpan="2" Content="{TemplateBinding Content}" />
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The content that is added to this template is a UserControl
. That all works.
But now I want to define a title in the UserControl
. To set the title, I made an attached property
'WindowDetails.Title'.
public static class WindowDetails
{
public static string GetTitle(DependencyObject obj)
{
return (string)obj.GetValue(TitleProperty);
}
public static void SetTitle(DependencyObject obj, string value)
{
obj.SetValue(TitleProperty, value);
}
// Using a DependencyProperty as the backing store for Title. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TitleProperty =
DependencyProperty.RegisterAttached("Title", typeof(string), typeof(WindowDetails), new PropertyMetadata(""));
}
And I set the the title in the UserControl
like this:
<UserControl x:Class="Something.View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dsControls="clr-namespace:Something"
Width="400"
dsControls:WindowDetails.Title="Test">
/** Some content **/
</UserControl>
The problem
I cannot bind the property value to the label in my template
.
What I already tried (and went wrong)
<Label Content="{Binding Path=(dsControls:WindowDetails.Title), RelativeSource={RelativeSource TemplatedParent}}"
FontSize="20" />
and
<Label Content="{Binding Path=(dsControls:WindowDetails.Title), RelativeSource={RelativeSource Self}}"
FontSize="20" />
Also, changing the OwnerType
of the Attached property
:
To WindowDetails
public static readonly DependencyProperty TitleProperty = DependencyProperty.RegisterAttached("Title", typeof(string), typeof(WindowDetails), new PropertyMetadata(""));
When I do this, the property is not set. But the content of the label
has the default property value
.
To UserControl
public static readonly DependencyProperty TitleProperty = DependencyProperty.RegisterAttached("Title", typeof(string), typeof(UserControl), new PropertyMetadata(""));
When I do this, the property is set, but the content of the label
has no value.
Question
How can I set the attached property
in my UserControl
and bind it to the content of the label
in my template?
Thanks in advance!
Greetings Loetn
Upvotes: 4
Views: 1927
Reputation: 18580
This is how you can do this: Give x:Name
to your ContentPresenter
and refer to it in binding the label.
<Border CornerRadius="8,8,0,0"
BorderBrush="{StaticResource BorderBrushColor}"
Background="{StaticResource HeaderColor}"
Grid.ColumnSpan="2"
Grid.Row="0">
<Label Content="{Binding Path=Content.(dsControls:WindowDetails.Title), ElementName="myPresenter"}" FontSize="20" />
</Border>
<ContentPresenter x:Name="myPresenter" Grid.Row="1" Grid.ColumnSpan="2" Content="{TemplateBinding Content}" />
Upvotes: 4
Reputation: 6547
Try using a converter
public class AttchedTitleToTitleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value as FrameworkElement).GetValue(WindowDetails.TitleProperty);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
Add it to your ResourceDictionary
:
<local:AttchedTitleToTitleConverter x:Key="titleConverter"/>
And in the binding:
<Label Content="{Binding RelativeSource={RelativeSource Self}, Converter={DynamicResource titleConverter}}"/>
Hope this helps
Upvotes: 3