【问题标题】:Foreground property behavior confusion前台属性行为混乱
【发布时间】:2011-07-26 19:34:07
【问题描述】:

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

    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>

如果我运行它,它会是这样的:

所以我的困惑是 ControlTemplate 中的 TextBlock 遵循 Foreground 的本地值。但是在 OnApplyTemplate 方法中添加的 TextBlock 遵循样式中的值。

但我想要的是一个仅在没有本地值存在时才遵循样式的 TextBlock。

那么为什么这两个 TextBlock 的行为不同,我如何才能获得一个仅在没有本地值存在时才遵循样式的 TextBlock?

注意:如何使自定义控件内的 TextBlocks 不 受网格资源中隐式样式的影响(其中 包含自定义控件)。

【问题讨论】:

    标签: .net wpf xaml custom-controls controltemplate


    【解决方案1】:

    当您为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>
    

    【讨论】:

    • 谢谢,这是解决问题的一种方法。但我想获得一个自定义控件,它只在没有本地值时遵循样式(在 Grid.Resources 中定义)。
    • 那么你在Grid.Resources 中的样式应该是CustomControl1 而不是TextBlock&lt;Style TargetType="{x:Type app1:CustomControl1}"&gt; &lt;Setter Property="Foreground" Value="Green"&gt;&lt;/Setter&gt; &lt;/Style&gt;
    • 谢谢,但我真正的问题是我想知道为什么两个 TextBlock 的行为不同。我想要一个在文本块样式存在时不会中断的自定义控件。
    • 意味着文本块样式并不适用于 CustomControl 而是适用于网格中的其他控件?你不应该使用隐式样式。将 x:Key 值赋予 Grid.Resources 样式。这是一个类似的问题stackoverflow.com/questions/5381018/…
    猜你喜欢
    • 1970-01-01
    • 2016-06-30
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    • 2017-10-13
    • 2015-03-15
    • 1970-01-01
    • 2021-02-22
    相关资源
    最近更新 更多