前景属性行为混淆

3

我有一个类似这样的自定义控件:

    public class CustomControl1 : Control
{
    private StackPanel panel;

    static CustomControl1()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
    }

    public override void OnApplyTemplate()
    {
        panel = (StackPanel)GetTemplateChild("root");
        panel.Children.Add(new TextBlock { Text = "TextBlock added in the OnApplyTemplate method" });

        base.OnApplyTemplate();
    }
}

它的控制模板如下:

<Style TargetType="{x:Type local:CustomControl1}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                <StackPanel Name="root">
                    <TextBlock>TextBlock added in ControlTemplate</TextBlock>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

然后我在主窗口中使用它:
<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    xmlns:app1="clr-namespace:WpfApplication1">
<Grid>
    <Grid.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="Foreground" Value="Green"></Setter>
        </Style>
    </Grid.Resources>

    <app1:CustomControl1 Foreground="Red">

    </app1:CustomControl1>
</Grid>

如果我运行它,它会像这样: enter image description here 所以我的困惑是ControlTemplate中的TextBlock遵循Foreground的本地值。但是在OnApplyTemplate方法中添加的TextBlock遵循样式的值。
但是我想要一个TextBlock,只有在没有本地值时才遵循样式。
那么为什么这两个TextBlock行为不同,如何获得一个只在没有本地值时遵循样式的TextBlock?
注意:如何使自定义控件内部的TextBlocks不受包含自定义控件的Grid资源中的隐式样式影响。
1个回答

2
当您为 Foreground 应用本地值时,您是将其应用于 CustomControl,而在样式中,您仅将其应用于 TextBlock,这会产生很大的区别。摆脱 Grid.Resources 并将您的样式设置器直接移动到 ControlTemplate 中,它将按预期工作。
<Style TargetType="{x:Type local:CustomControl1}">
    <Setter Property="Foreground" Value="Green"></Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                <StackPanel Name="root">
                    <TextBlock>TextBlock added in ControlTemplate</TextBlock>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

谢谢,这是解决问题的一种方法。但我想要一个自定义控件,只有在没有本地值时才遵循网格资源中定义的样式。 - Cui Pengfei 崔鹏飞
那么你在 Grid.Resources 中的样式应该是针对 CustomControl1 而不是 TextBlock<Style TargetType="{x:Type app1:CustomControl1}"> <Setter Property="Foreground" Value="Green"></Setter> </Style> - anivas
谢谢,但我的真正问题是我想知道为什么这两个TextBlock的行为不同。而且我想要一个自定义控件,在文本块的样式存在时不会被中断。 - Cui Pengfei 崔鹏飞
这意味着textblock样式不是用于CustomControl,而是用于网格中的其他控件?那么您不应该使用隐式样式。给Grid.Resources样式设置x:Key值。这里有一个类似的问题http://stackoverflow.com/questions/5381018/override-typed-textblock-style-for-contentpresenter-in-wpf - anivas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接