I have a user control which is an icon container.
<Rectangle x:Name="Rectangle"
Width="{Binding SquareWidth}"
Height="{Binding SquareWidth}"
Fill="{Binding FillBrush}"
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}, Mode=OneWay}">
<Rectangle.OpacityMask>
<VisualBrush Visual="{Binding VisualItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Stretch="UniformToFill" />
</Rectangle.OpacityMask>
</Rectangle>
And in the code-behind:
public static readonly DependencyProperty CanvasItemDependencyProperty =
DependencyProperty.Register(nameof(VisualItem), typeof(Canvas),
typeof(SquareIcon), new FrameworkPropertyMetadata());
public Canvas VisualItem
{
get => GetValue(CanvasItemDependencyProperty) as Canvas;
set => SetValue(CanvasItemDependencyProperty, value);
}
The icon drawings are defined as Canvas items in a resource dictionary:
<Canvas x:Key="appbar_3d_3ds" Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
<Path Width="32" Height="40" Canvas.Left="23" Canvas.Top="18" Stretch="Fill" Fill="{DynamicResource BlackBrush}" Data="F1 M 27,18L 23,26L 33,30L 24,38L 33,46L 23,50L 27,58L 45,58L 55,38L 45,18L 27,18 Z "/>
</Canvas>
I instantiate my user control in the main form like this:
<controls:SquareIcon VisualItem="{StaticResource appbar_information_circle}" Width="16" Height="16" FillBrush="Black" SquareWidth="16" Margin="0,0,5,0"/>
But all I get is a transparent square.
If I replace the "Binding VisualItem" by "StaticResource appbar_information_circle", the icon shows up.
What am I missing?
You did not follow mandatory naming conventions for dependency properties. The identifier field of a dependency property called VisualItem
must be named VisualItemProperty
, otherwise the XAML parser can't resolve it.
public static readonly DependencyProperty VisualItemProperty =
DependencyProperty.Register(
nameof(VisualItem), typeof(Canvas), typeof(SquareIcon));
public Canvas VisualItem
{
get => (Canvas)GetValue(VisualItemProperty)
set => SetValue(VisualItemProperty, value);
}
It is not useful to use the as
operator in the property getter, because the property value is always a Canvas. In case it's not (which is a programming error) wou'll want to get an InvalidCastException instead of a NullReferenceException.
You should also consider to change the type of your dependency property from Canvas to Visual
. It would work the same way, but provide greater flexibility in terms of which elements could be assigned to the property.
As a note, setting Mode=TwoWay
and UpdateSourceTrigger=PropertyChanged
on the Visual Binding is pointless. The Binding should just look like this:
<VisualBrush Visual="{Binding VisualItem}" .../>