Как наследовать свойство XAML и переопределить свойство дочернего элемента?

мы только начали работать с XAML и по-прежнему боремся с основными проблемами: Исходя из CSS, мы хотели бы определить общий стиль кнопки с настраиваемым шаблоном управления, а затем второй стиль наследуем все, начиная с первого стиля, используя "basedon". Этот второй стиль затем должен переопределять такие свойства, как "цвет переднего плана" (который работает) но также свойства дочерних элементов в нашем пользовательском шаблоне, такие как "цвет фона", например, включенный элемент границы и т.д. (который не работает).

Каков общий подход к подобным вещам? Как далеко мы можем пойти с каскадными стилями?

Ура!

Ответы

Ответ 1

Вы можете использовать унаследованный стиль без ссылки на ключ:

<Grid>
    <Grid.Resources>
        <!-- Definition of default appearance of a button -->
        <Style TargetType="Button" x:Key="Default">
            <Setter Property="Background" Value="Red"></Setter>
            <Setter Property="FontFamily" Value="Segoe Black" />
            <Setter Property="HorizontalAlignment" Value="Center" />
            <Setter Property="FontSize" Value="32pt" />
            <Setter Property="Foreground" Value="#777777" />
        </Style>
        <!-- Define general style that based is base on the default style of the button without a key reference-->
        <Style TargetType="Button" BasedOn="{StaticResource Default}"/>

        <!-- In sub style override the properties you need -->
        <Style BasedOn="{StaticResource Default}" TargetType="Button" x:Key="SubButton" >
            <Setter Property="FontSize" Value="8pt" />
        </Style>

    </Grid.Resources>

    <Button Content="Main" Height="51" HorizontalAlignment="Left" Margin="154,72,0,0" Name="button1" VerticalAlignment="Top" Width="141" />
    <Button Content="Sub" Style="{StaticResource SubButton}" Height="51" HorizontalAlignment="Left" Margin="154,162,0,0" Name="button2" VerticalAlignment="Top" Width="141" />
</Grid>

Ответ 2

У меня есть (в моем приложении WPF) стили default (base), определенные в ResourceDictionary в App.xaml(в проекте запуска). Например, для кнопки следующим образом.

    <Style TargetType="Button">
        <Setter Property="Margin" Value="5"/>
        <Setter Property="FontWeight" Value="DemiBold"/>
        <Setter Property="FontSize" Value="16"/>
    </Style>

Во всех представлениях я использую (по умолчанию) этот общий стиль (автоматически унаследованный)! Когда мне нужно изменить или добавить какое-либо свойство в стиле по умолчанию (определенное в App.xaml), я создаю новый стиль, основанный на стиле по умолчанию.

    <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
        <!-- change -->
        <Setter Property="Margin" Value="10" />
        <!-- add -->
        <Setter Property="Foreground" Value="Red" />
    </Style>

Когда мне нужен скрытый или сильно переопределенный стиль по умолчанию (в некотором смысле), я создаю новый стиль (основанный на ничего).

    <Style TargetType="Button"/>

Вы, конечно, можете продолжить наследование в App.xaml или в определенном представлении. Вы можете создать новый стиль с именем по умолчанию и использовать новый стиль по имени. Например, стиль RedButton и GreenButton.

    <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}" x:Key="RedButton">
        <Setter Property="Foreground" Value="Red" />
    </Style>

    <Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}" x:Key="GreenButton">
        <Setter Property="Foreground" Value="Green" />
    </Style>

Etc...

ПРИМЕЧАНИЕ: вместо этого определите свой стиль в App.xaml, вы можете использовать автономную библиотеку (dll) только с стилями и ResourceDictionary из вашей библиотеки в App.xaml ResourceDictionary.MergedDictionaries.

Ответ 3

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

Например, это создает шаблон кнопки с элементом управления границей и привязывает фон границы к свойству Background Button. Установив свойство Background для Button в других стилях, он изменит свойство Background на границе.

<StackPanel>
    <StackPanel.Resources>
        <Style x:Key="BaseButtonStyle" TargetType="Button">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}">
                            <ContentPresenter/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="BlueButtonStyle" TargetType="Button"
               BasedOn="{StaticResource BaseButtonStyle}">
            <Setter Property="Background" Value="Blue"/>
        </Style>
        <Style x:Key="RedButtonStyle" TargetType="Button"
               BasedOn="{StaticResource BaseButtonStyle}">
            <Setter Property="Background" Value="Red"/>
        </Style>
    </StackPanel.Resources>
    <Button Style="{StaticResource RedButtonStyle}">Red</Button>
    <Button Style="{StaticResource BlueButtonStyle}">Blue</Button>
</StackPanel>

Многие из свойств в Control предназначены для использования в шаблонах управления и не будут влиять на другое поведение, если они изменены. Это BorderBrush, BorderThickness, Background, Padding, HorizontalContentAlignment и VerticalContentAlignment.