Как параллель с DRY для кода, мне не нравится иметь одинаковые присваивания свойств в XAML. Я видел примеры кода, где довольно много кода можно объединить как стиль. Как только это будет сделано и очищено, больше кода можно будет представить другим стилем, основанным на исходном стиле, который имеет некоторые более специфические правки и так далее. Наступает момент, когда это приводит к стилям, которые являются «умными». Изменение одного из стилей приводит к каскадному влиянию на всех тех, кто от него зависит. Есть ли практическое правило или общие рекомендации, которые следует помнить при использовании Style ... BasedOn={...}?

Пример из Head First C # и с использованием версии WPF . На странице 754 приведен пример, показанный ниже. Поскольку это введение, существует несколько назначений свойств, которые можно объединить с помощью стилей.

    <StackPanel Margin="20">
        <TextBlock Foreground="White" FontFamily="Segoe" FontSize="20px"
                   FontWeight="Bold" Text="{Binding TeamName}" />
        <TextBlock Foreground="White" FontFamily="Segoe" FontSize="16px" 
                   Text="Starting Players" Margin="0,5,0,0"/>
        <ListView Background="Black" Foreground="White"  Margin="0,5,0,0"
                                   ItemTemplate="{StaticResource PlayerItemTemplate}"
                                   ItemsSource="{Binding Starters}" />
        <TextBlock Foreground="White"  FontFamily="Segoe" FontSize="16px"
                   Text="Bench Players" Margin="0,5,0,0"/>
        <ListView Background="Black" Foreground="White" ItemsSource="{Binding Bench}" 
                  ItemTemplate="{StaticResource PlayerItemTemplate}" Margin="0,5,0,0"/>
    </StackPanel>

Рефакторинг с использованием стилей для удаления дублированных назначений свойств. Это показывает промежуточный шаг, где свойство Margin может быть дополнительно консолидировано.

<StackPanel Margin="20">
    <StackPanel.Resources>
        <Style x:Key="whiteForground" TargetType="TextBlock">
            <Setter Property="Foreground" Value="White" />
            <Setter Property="FontFamily" Value="Segoe" />
        </Style>
        <Style TargetType="ListView">
            <Setter Property="Margin" Value="0,5,0,0" />
            <Setter Property="Background" Value="Black" />
            <Setter Property="Foreground" Value="White" />
        </Style>
        <Style x:Key="appliedMargin" TargetType="TextBlock" BasedOn="{StaticResource whiteForground}">
            <Setter Property="Margin" Value="0,5,0,0" />
        </Style>
    </StackPanel.Resources>
    <TextBlock Style="{StaticResource whiteForground}" FontSize="20px"
                FontWeight="Bold" Text="{Binding TeamName}" />
    <TextBlock Style="{StaticResource appliedMargin}" FontSize="16px"
                Text="Starting Players" />
    <ListView ItemTemplate="{StaticResource PlayerItemTemplate}"
                ItemsSource="{Binding Starters}" />

    <TextBlock Style="{StaticResource appliedMargin}" FontSize="16px"
                Text="Bench Players" />
    <ListView ItemsSource="{Binding Bench}"
                ItemTemplate="{StaticResource PlayerItemTemplate}" />
</StackPanel>
0
IvenBach 11 Апр 2019 в 22:24

2 ответа

Лучший ответ

Я стараюсь придерживаться только одного уровня на основе.

Таким образом, базовый стиль, только один стиль наследования (лист).

Но, очевидно, с установленными значениями, переопределяющими любой элемент управления, на котором используется лист.

Максимум другой слой.

На это есть несколько причин.

1)

Это сложное наследство, отслеживающее кошмар - как вы, наверное, поняли.

2 )

Раньше была (и, вероятно, все еще есть) потенциальная проблема с цепочкой словаря ресурсов (rd).

То, что вы хотите сделать, это иметь ваши стили в RD.

Они часто становятся большими довольно быстро.

Таким образом, вы разделили их на ряд.

Вы хотите основывать одно на другом, так что вам нужно знать о базовом стиле. Поэтому вы объединяете базовый в листе.

Один слой словарей слияния как:

<ResourceDictionary 
...
<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary  Source="pack://application:,,,/Blaa.Validation.UILib;component/Resources/UIlibResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type ComboBox}"   BasedOn="{StaticResource ErrorStyle}"/>
<Style TargetType="{x:Type DatePicker}" BasedOn="{StaticResource ErrorStyle}"/>

Здесь стиль комбинированного списка основан на стиле ошибок в UILib Resources.

Это нормально работает.

Если третий объединяет другой, то, в свою очередь, объединяет другой ... и так далее.

У вас могут быть загадочные проблемы, которые могут возникнуть из-за задержки слияния.

Я видел периодически возникающие ошибки и проблемы со стилем.

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

Это могло быть исправлено в последних версиях фреймворка, но я ничего не упомянул об этом, и в течение довольно долгого времени в WPF мало что изменилось.

3 )

Слишком легко найти, что вам нужен этот уровень до этого, но это зависит от чего-то еще, если вы попытаетесь стать слишком «умным».

Было бы здорово, если бы стили каскадировались или были миксины, но их нет, а у нас нет.

Так что все это основано на материалах, которые у нас есть, и это немного неуклюже по сравнению с сетью.

1
Andy 12 Апр 2019 в 08:55

Взгляните на приоритет свойства значения зависимости

0
ZJ.Wang 12 Апр 2019 в 05:04