Consider the follow 2 XAML snippets (which are side-by-side in the file):
<Button
x:Name="BuyButton"
Margin="0,0,1,1"
IsEnabled="{Binding CanBuy}"
>
<StackPanel
DataContext="{Binding Product}">
<TextBlock
Foreground="Red"
Text="BUY" />
<TextBlock
Foreground="Red"
Text="{Binding BuyPrice}" />
</StackPanel>
</Button>
<Button
x:Name="SellButton"
Margin="0,0,1,1"
IsEnabled="{Binding CanSell}"
>
<StackPanel
DataContext="{Binding Product}">
<TextBlock
Foreground="Red"
Text="SELL" />
<TextBlock
Foreground="Red"
Text="{Binding SellPrice}" />
</StackPanel>
</Button>
How does one remove duplication in WPF? I have approx 4 uses (2 shown here) of this type of button, and they're 80% the same, if not more. I could extract this into a user control and put a few DPs on it and then I'd have one control, but I fear that I will start littering my code base with tons of user controls (I have a lot of "one-off" situations like this). I don't like the DataTemplate solution here because I'd still need two templates, which would have repeated code. Without creating a bunch of templates/controls, is there a way of making this code follow DRY?
A ControlTemplate might work:
<ControlTemplate x:Key="ButtonControlTemplate1" TargetType="{x:Type Button}">
<StackPanel Height="Auto" Width="Auto">
<TextBlock Text="{TemplateBinding Content}" Foreground="Red"/>
<TextBlock Text="{TemplateBinding Tag}" Foreground="Red"/>
</StackPanel></ControlTemplate>
I used TemplateBinding to get the two changeable pieces of data. Now when you create the button, apply the Template, and set the Bindings to your elements:
<Button x:Name="BuyButton"
Margin="0,0,1,1"
IsEnabled="{Binding CanBuy}"
Template="{DynamicResource ButtonControlTemplate1}"
Content="Button"
Tag="{Binding BuyPrice}"/>
The only thing missing is the DataContext: just set it at a container above the two buttons.
I haven't tried it specifically, but it seems it should work. I chose "Tag" above because I needed a second element for Binding. I'd love to see different suggestions about this.
You probably also want to break the ForegroundColor="Red" type stuff into a style.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With