为什么有些WPF自定义样式元素被忽略,而其他人则被忽略了?

时间:2015-10-19 18:21:20

标签: wpf xaml wpf-style

我有点困惑,试图理解视觉树中的样式覆盖是如何工作的。

我有两个例子 - 第一个,定义DataGridCell完美无缺,如图所示。

第二个,定义ToggleButton,完全被忽略,但我很难找到第一个有效的原因,但第二个没有。任何人都可以提供任何见解吗?

工作 - DataGridCell样式定义在DataGrid.Resources

<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding hello}">
    <DataGrid.Resources>
        <Style TargetType="{x:Type DataGridCell}"><!--DataGridCell is a child of DataGrid's Visual Tree -->
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Border Padding="10" Background="Red">
                          <ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" />
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGrid.Resources>

working

非工作 - ToggleButton Resources中定义的样式将被忽略:

<Expander>
    <Expander.Resources>
        <Style TargetType="{x:Type ToggleButton}"><!--ToggleButton is a child of Expander's Visual Tree-->
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <TextBlock>Hello World!</TextBlock>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Expander.Resources>
    <Expander.Header>Header</Expander.Header>
    <Expander.Content>Body</Expander.Content>
</Expander>

enter image description here

1 个答案:

答案 0 :(得分:2)

某些控件为其使用的控件定义了自己的Styles。例如,Expander的默认模板为ControlTemplate定义了ToggleButton并将其设置为这样(我不想复制整个默认样式,因为它很长):

<ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" 
    ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}" 
    Content="{TemplateBinding Header}" ... Style="{StaticResource ExpanderDownHeaderStyle}" ... />

<Style x:Key="ExpanderDownHeaderStyle" TargetType="{x:Type ToggleButton}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ToggleButton}">
                <Border Padding="{TemplateBinding Padding}">
                    <Grid Background="Transparent" SnapsToDevicePixels="False">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="19"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Ellipse x:Name="circle" Fill="{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}" VerticalAlignment="Center" Width="19"/>
                        <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                        <ContentPresenter Grid.Column="1" HorizontalAlignment="Left" Margin="4,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="true">
                        <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="true">
                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                        <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

因为这是一个本地值,所以它优先于定义为资源的样式 正如dkozl在评论中提到的那样,检查Dependency Property Setting Precedence List以找出哪个优先于什么。