5

考虑以下 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

4 回答 4

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:只需将其设置在两个按钮上方的容器中。

我没有具体尝试过,但它似乎应该可以工作。我选择了上面的“标签”,因为我需要第二个元素进行绑定。我很想看到关于这个的不同建议。

您可能还想将 ForegroundColor="Red" 类型的内容分解为一种样式。

于 2009-03-09T21:11:15.117 回答
2

I don't have an alternative solution but I disagree on your argument of one-off controls. In my opinion it boils down to choosing between a lot of duplicate code or less duplication with a number of control that are quite specific. If this were plain code you would probably not think twice about performing an extract method when confronted with several chunks of identical code, why is the fact that this code is now XAML make your decision any different?

于 2009-03-09T20:58:09.487 回答
2

If your goal is just to reduce repetition, you can eliminate a lot of it by using Styles and setting common attached properties on a parent element:

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

Note that this ends up being more code... which is why "3 strikes, then refactor" is the rule of thumb.

于 2009-03-09T21:07:51.083 回答
0

Separate it into a user control. DRY principles and refactoring should be treated the same across just about any platform.

于 2009-03-09T21:00:25.890 回答