I'm creating a custom UserControl which will act as a container, showing a self-sized watermark behind its Content.
The relevant part of the ControlTemplate (I'll give you the full thing below) is
<TextBlock
Text="{TemplateBinding WatermarkText}"
Foreground="{TemplateBinding WatermarkBrush}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold">
<TextBlock.LayoutTransform>
<RotateTransform Angle="{Binding WatermarkAngle,RelativeSource={RelativeSource AncestorType={x:Type local:WatermarkUserControl}}}"/>
</TextBlock.LayoutTransform>
</TextBlock>
My UserControl has dependency properties for WatermarkText, WatermarkBrush, WatermarkAngle and WatermarkVisibility (I'll include that below). Notice that the TemplateBindings for WatermarkText, WatermarkBrush and WatermarkVisibility all work fine.
Using TemplateBinding for WatermarkAngle didn't work, because TemplateBinding is a lightweight "binding", so it doesn't support inheritance context. The WatermarkAngle binding that I ended up with (above) actually works; and yet a binding error is reported:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='[redacted namespace].WatermarkUserControl', AncestorLevel='1''. BindingExpression:Path=WatermarkAngle; DataItem=null; target element is 'RotateTransform' (HashCode=59772470); target property is 'Angle' (type 'Double')
So is there a way of doing this better, which avoids the error being reported? And why is it reporting an error with the binding, given that the binding is actually working? (If I change the value, it reflects that.)
That concludes the question. Here are all the parts you need, to satisfy MCVE:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
public class WatermarkUserControl : UserControl
{
public static readonly DependencyProperty WatermarkTextProperty =
DependencyProperty.Register(nameof(WatermarkText), typeof(string), typeof(WatermarkUserControl), new PropertyMetadata("Watermark"));
public static readonly DependencyProperty WatermarkBrushProperty =
DependencyProperty.Register(nameof(WatermarkBrush), typeof(Brush), typeof(WatermarkUserControl), new PropertyMetadata(new SolidColorBrush(Colors.LightGray)));
public static readonly DependencyProperty WatermarkAngleProperty =
DependencyProperty.Register(nameof(WatermarkAngle), typeof(double), typeof(WatermarkUserControl), new PropertyMetadata(0d));
public static readonly DependencyProperty WatermarkVisibilityProperty =
DependencyProperty.Register(nameof(WatermarkVisibility), typeof(Visibility), typeof(WatermarkUserControl), new PropertyMetadata(Visibility.Visible));
public string WatermarkText
{
get { return (string)GetValue(WatermarkTextProperty); }
set { SetValue(WatermarkTextProperty, value); }
}
public Brush WatermarkBrush
{
get { return (Brush)GetValue(WatermarkBrushProperty); }
set { SetValue(WatermarkBrushProperty, value); }
}
public double WatermarkAngle
{
get { return (double)GetValue(WatermarkAngleProperty); }
set { SetValue(WatermarkAngleProperty, value); }
}
public Visibility WatermarkVisibility
{
get { return (Visibility)GetValue(WatermarkVisibilityProperty); }
set { SetValue(WatermarkVisibilityProperty, value); }
}
}
ResourceDictionary:
<Style x:Key="WatermarkUserControlBaseStyle" TargetType="local:WatermarkUserControl">
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:WatermarkUserControl">
<Grid>
<local:NoSizeDecorator Visibility="{TemplateBinding WatermarkVisibility}">
<Viewbox>
<TextBlock
Text="{TemplateBinding WatermarkText}"
Foreground="{TemplateBinding WatermarkBrush}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold">
<TextBlock.LayoutTransform>
<RotateTransform Angle="{Binding WatermarkAngle,RelativeSource={RelativeSource AncestorType={x:Type local:WatermarkUserControl}}}"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Viewbox>
</local:NoSizeDecorator>
<ContentPresenter Content="{TemplateBinding Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="DraftWatermarkStyle" TargetType="local:WatermarkUserControl" BasedOn="{StaticResource WatermarkUserControlBaseStyle}">
<Setter Property="WatermarkText" Value="DRAFT"/>
<Setter Property="WatermarkBrush" Value="LightPink"/>
<Setter Property="WatermarkAngle" Value="-20"/>
</Style>
NoSizeDecorator is defined here.
Example of use:
<local:WatermarkUserControl
Style="{StaticResource DraftWatermarkStyle}"
WatermarkVisibility="True">
<StackPanel>
<Label Content="Mr Smith"/>
<Label Content="1 High Street"/>
<Label Content="London"/>
</StackPanel>
</local:WatermarkUserControl>
RelativeSource={RelativeSource TemplatedParent}
? – ClemensSystem.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=WatermarkAngle; DataItem=null; target element is 'RotateTransform' (HashCode=46828374); target property is 'Angle' (type 'Double')
– Richardissimo