Как избежать дублирования в WPF (после DRY) - PullRequest
4 голосов
/ 09 марта 2009

Рассмотрим следующие 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 ]

3 голосов
/ 10 марта 2009

Шаблон управления может работать:

<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" на стиль.

2 голосов
/ 10 марта 2009

Если ваша цель - просто уменьшить количество повторений, вы можете устранить многие из них, используя стили и задав общие свойства для родительского элемента:

<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 удара, а затем рефакторинг" - это практическое правило.

2 голосов
/ 09 марта 2009

У меня нет альтернативного решения, но я не согласен с вашим аргументом об одноразовом контроле. По моему мнению, это сводится к выбору между большим количеством дублирующегося кода или меньшим количеством дубликатов с рядом довольно специфических элементов управления. Если бы это был простой код, вы, вероятно, не задумывались бы дважды о выполнении метода извлечения, когда сталкивались с несколькими кусками идентичного кода, почему тот факт, что этот код теперь является XAML, делает ваше решение другим?

0 голосов
/ 10 марта 2009

Разделите его на пользовательский элемент управления. Принципы СУХОГО и рефакторинга должны одинаково применяться практически на любой платформе.

...