避免WPF中的重复(DRY之后)

时间:2009-03-09 20:20:25

标签: wpf dry

考虑以下2个XAML片段(在文件中并排):

<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>

如何删除WPF中的重复?这种按钮有大约4次使用(这里显示2次),如果不是更多,它们的相同之处是80%。我可以将它提取到用户控件中并在其上放置几个DP然后我有一个控件,但我担心我会开始乱扔垃圾我的代码库有大量的用户控件(我有很多“一次性” “像这样的情况)。我不喜欢这里的DataTemplate解决方案,因为我仍然需要两个模板,这些模板会重复代码。如果没有创建一堆模板/控件,有没有办法让这些代码遵循DRY?

4 个答案:

答案 0 :(得分:3)

ControlTemplate可能有效:

<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>  

我使用TemplateBinding来获取两个可变数据。现在,当您创建按钮时,应用模板,并将绑定设置为元素:

<Button x:Name="BuyButton"
    Margin="0,0,1,1"
    IsEnabled="{Binding CanBuy}"
    Template="{DynamicResource ButtonControlTemplate1}"
    Content="Button" 
    Tag="{Binding BuyPrice}"/>

唯一缺少的是DataContext:只需将其设置在两个按钮上方的容器中即可。

我没有特别试过,但它似乎应该有效。我在上面选择了“Tag”,因为我需要第二个元素用于Binding。我很乐意看到不同的建议。

您可能还想将ForegroundColor =“Red”类型的东西分解为样式。

答案 1 :(得分:2)

我没有替代解决方案,但我不同意你关于一次性控制的论点。在我看来,它归结为在大量重复代码之间进行选择,或者通过一些非常具体的控制来减少重复。如果这是普通的代码,你可能不会在面对几个相同代码的块时执行提取方法,现在为什么这个代码现在是XAML让你的决定有所不同?

答案 2 :(得分:2)

如果你的目标只是减少重复,你可以通过使用样式并在父元素上设置常见的附加属性来消除大量重复:

<StackPanel>
    <StackPanel.Resources>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Margin" Value="0,0,1,1"/>
        </Style>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="Foreground" Value="Red"/>
            <Setter Property="DataContext" Value="{Binding Product}"/>
        </Style>
    </StackPanel.Resources>
    <Button x:Name="BuyButton" IsEnabled="{Binding CanBuy}">
        <StackPanel>
            <TextBlock Text="BUY"/>
            <TextBlock Text="{Binding BuyPrice}"/>
        </StackPanel>
    </Button>
    <Button x:Name="SellButton" IsEnabled="{Binding CanSell}">
        <StackPanel>
            <TextBlock Text="SELL"/>
            <TextBlock Text="{Binding SellPrice}"/>
        </StackPanel>
    </Button>
</StackPanel>

请注意,这最终会成为更多代码...这就是为什么“3次攻击,然后是重构”是经验法则。

答案 3 :(得分:0)

将其分隔为用户控件。几乎任何平台都应该对DRY原则和重构进行相同的处理。