首页 > 解决方案 > 如果已设置样式,如何覆盖 WPF 子控件样式?

问题描述

如果我有一个简单的子控件,它已经为子控件中的元素定义了样式。我可以从父控件更改该元素的样式吗?

如果我没有在子控件中设置样式,我可以从父控件覆盖它,但是在设置样式时我似乎无法让它工作。

我无法更改子控件中的代码。

示例子控件:

    <UserControl
    x:Class="TestingThemes.ChildControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:TestingThemes"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    d:DesignHeight="450"
    d:DesignWidth="800"
    mc:Ignorable="d">
    <UserControl.Resources>
        <Style x:Key="aw" TargetType="Button">
            <Setter Property="Foreground" Value="Blue" />
        </Style>
    </UserControl.Resources>
    <Grid>
        <Button
            Width="100"
            Height="50"
            Content="Kalle Anka"
            <!-- If I remove the style I can override it from parent control -->
            Style="{DynamicResource aw}" />
    </Grid>
</UserControl>

父控件:

 <Grid>
    ...            
    <local:ChildControl>
        <local:ChildControl.Resources>
            <!--<Style BasedOn="{StaticResource local:ResourceKey=aw}" TargetType="Button">-->
            <Style TargetType="Button">
                <Setter Property="Foreground" Value="Red" />
            </Style>
        </local:ChildControl.Resources>
    </local:ChildControl>
   
</Grid>

标签: c#wpfxaml

解决方案


这是可能的,但您必须更改初始Style. XAML 引擎将遍历逻辑树以查找StaticResource/DynamicResource资源以查找从本地开始的元素(例如Button),本地ResourceDictionary.

这意味着,您希望在查找路径的最后找到在Style内部定义的默认值UserControl- 在任何旨在覆盖默认值的潜在自定义样式之后Style。为此,您必须将其Style移至App.xamlGeneric.xaml
此外,引用必须是DynamicResource为了将查找推迟到组成逻辑树的那一刻。Style可以在通往树根的路径上的任何位置定义覆盖。

由于Generic.xaml提供了不同的名称范围,因此您必须定义一个唯一的静态(就 XAML 名称范围而言是全局的)ComponentResourceKey,您必须将其用作样式的x:Key值(以防您计划将默认样式移动到Generic.xaml文件)。

由于前面提到的 XAML 资源查找行为,当您计划使控件可自定义(如您的情况)时,创建自定义Control总是比 a 更可取。UserControl默认情况下Style,自定义的默认值Control位于Generic.xaml中,因此您永远不会遇到当前问题。

ChildControl.xaml

<UserControl>
  <Grid>
    <Button Style="{DynamicResource aw}" />
  </Grid>
</UserControl>

App.xaml Generic.xaml之前
的最后一个查找位置。如果尚未找到具有相同密钥的a,则将应用找到的 in 。StyleStyleApp.xaml

<Style x:Key="aw" TargetType="Button">
  <Setter Property="Foreground" Value="Blue" />
</Style>

父控件.xaml

<ChildControl>
  <ChildControl.Resources>
    <Style x:Key="aw" TargetType="Button">
      <Setter Property="Foreground" Value="Red" />
    </Style>
  </ChildControl.Resources>
</ChildControl>

推荐阅读