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
Contentproperty in the<Style x:Key="inputSplitIconButton">.- But how do I parameterize the
Drawing=""attribute?
- But how do I parameterize the
- Set the
DataTemplateproperty in the<Style x:Key="inputSplitIconButton">and use aDataContextbinding for theDrawing=""attribute, and pass that in as the newDataContextfor 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
Tagproperty to store theStaticResourcename.
- Use an Attached Property to set the attribute in the
- Subclass
Buttonand 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?