My application (using MahApps.Metro
) has a lot of <Button>
elements with Content
that all have identical markup except for varying attributes on the <Button>
itself, as well as a single Button.Content
child element attribute that I want to parameterize through a new attribute (an Attached Property?) on the <Button>
.
I have about 20 instances of this XAML for a button:
<Button
Style="{StaticResource MetroCircleButtonStyle}"
Margin="0,-4,-4,2"
DockPanel.Dock="Right"
Width="32"
Height="32"
Name="targetSystemAutoconfigureButton"
ToolTip="{x:Static me:Resources.Settings_AutoconfigureTargetSystem}"
Command="{Binding AutoconfigureTargetSystemCommand}"
>
<Button.Content>
<Rectangle Fill="{Binding Foreground, ElementName=targetSystemAutoconfigureButton}" Width="12" Height="12">
<Rectangle.OpacityMask>
<DrawingBrush Drawing="{StaticResource appbar_magnify}" Stretch="Uniform" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
I've already shrunk it down by moving the constant properties to a derived style:
<!-- In a <ResourceDictionary> located elsewhere -->
<Style x:Key="inputSplitIconButton" TargetType="Button" BasedOn="{StaticResource MetroCircleButtonStyle}">
<Setter Property="Margin" Value="0,-4,-4,2" />
<Setter Property="DockPanel.Dock" Value="Right" />
<Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" />
</Style>
<!-- Button XAML is now: -->
<Button
Style="{StaticResource inputSplitIconButton}"
Name="targetSystemAutoconfigureButton"
ToolTip="{x:Static me:Resources.Settings_AutoconfigureTargetSystem}"
Command="{Binding AutoconfigureTargetSystemCommand}"
>
<Button.Content>
<Rectangle Fill="{Binding Foreground, ElementName=targetSystemAutoconfigureButton}" Width="12" Height="12">
<Rectangle.OpacityMask>
<DrawingBrush Drawing="{StaticResource appbar_magnify}" Stretch="Uniform" />
</Rectangle.OpacityMask>
</Rectangle>
</Button.Content>
</Button>
But I want to have just this:
<Button
Style="{StaticResource inputSplitIconButton}"
Name="targetSystemAutoconfigureButton"
ToolTip="{x:Static me:Resources.Settings_AutoconfigureTargetSystem}"
Command="{Binding AutoconfigureTargetSystemCommand}"
ImageMask="{StaticResource appbar_magnify}" <--- this property
/>
A problem with WPF is that there's at least three different ways to accomplish the same end result, however I don't know WPF well enough to choose the best at this point. I know my options are:
- Set the
Content
property in the<Style x:Key="inputSplitIconButton">
.- But how do I parameterize the
Drawing=""
attribute?
- But how do I parameterize the
- Set the
DataTemplate
property in the<Style x:Key="inputSplitIconButton">
and use aDataContext
binding for theDrawing=""
attribute, and pass that in as the newDataContext
for that button instance- But this means I can't use my existing Bindings.
- Along the lines of adding a
DataTemplate
, there are variations-on-a-theme:- Use an Attached Property to set the attribute in the
DataTemplate
- Abuse the
Tag
property to store theStaticResource
name.
- Use an Attached Property to set the attribute in the
- Subclass
Button
and add my own properties there and create the content structure in code.- This will be very painful and is very non-idiomatic WPF.
- Define an Attached Property ("
me:Drawing=""
" for example), that when set on an element automatically adds the<Rectangle>...
etc child content.- Is this "correct" and idiomatic WPF? How does an Attached Property get to manipulate the markup of its applied element?