为什么一个setter需要一个TargetName而另一个不需要?

时间:2014-06-02 15:36:57

标签: wpf xaml

我正在搞乱样式和设置器因为我想学习创建自定义列表框选择的样式。

这是我拥有的

     <Style x:Key="{x:Type ListBoxItem}" 
         TargetType="{x:Type ListBoxItem}">
            <Setter Property="Height" Value="66" />           
            <Setter Property="Template">
                <Setter.Value>

                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <TextBlock x:Name="tb" >
                            <ContentPresenter Name="listItemContent" 
                              Grid.RowSpan="2" 
                              HorizontalAlignment="Left" 
                              Width="300" 
                              Margin="0,0,0,0" />
                        </TextBlock>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="true">
                                <Setter Property="Foreground" Value="Green"/>
                                <Setter Property="Background" TargetName="tb" Value="Black"/>
                            </Trigger>                            
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Foreground" Value="Purple"/>
                                <Setter Property="Background" Value="White"/>
                            </Trigger>
                        </ControlTemplate.Triggers>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

这很好用。但是,您会注意到ControlTemplate.Triggers部分中有IsSelected=TrueIsSelected=False的触发器

在这两个触发器中有两个setter。一个用于ForeGround,另一个用于Background

我的问题是,为什么只有背景设定者需要TargetName?为什么都不需要呢?它为什么需要呢?

3 个答案:

答案 0 :(得分:2)

虽然我已经意识到这个问题已经有两个正确的答案,但我并不认为它们符合Stack Overflow中常见的高标准。因此,我提供了相同的正确答案,但有更多的参考和信息。

如果查看MSDN上的Control.Foreground Property页面,您将看到名为依赖项属性信息的部分。在该部分中,您将看到:

enter image description here

请注意,会显示FrameworkPropertyMetadata.Inherits Property。在链接页面中,此获取或设置一个值,该值指示依赖项属性的值是否可继承。因此,我们了解到Control.Foreground DependencyProperty值将由子控件继承。

现在,如果你在依赖属性信息部分查看MSDN上的Control.Background Property页面,你会看到:

enter image description here

您会注意到此页面中缺少FrameworkPropertyMetadata.Inherits属性。这意味着子控件继承的Control.Background属性值

因此,您不需要为Foreground属性指定Setter.TargetName Property值的原因是因为没有为其指定目标,该值实际上将应用于整个{{1}然后该值将由ListBoxItem中的所有子控件继承。

答案 1 :(得分:1)

我相信这是因为Foreground属性是继承的,而Background属性则不是。请参阅以下内容:Property Value Inheritance

答案 2 :(得分:1)

如果未指定目标名称,则setter会将其修改应用于ControlTemplate(ListBoxItem)所针对的元素。默认情况下,在WPF中继承Foreground属性,因此它也将应用于TextBlock。

如果您不想为Background指定目标名称,可以使用TemplateBinding,它会将您的背景绑定到ListBoxItem的背景:

<ControlTemplate TargetType="{x:Type ListBoxItem}">
    <TextBlock Background={TemplateBinding Background}>
        <ContentPresenter Name="listItemContent" 
          Grid.RowSpan="2" 
          HorizontalAlignment="Left" 
          Width="300" 
          Margin="0,0,0,0" />
    </TextBlock>
    <ControlTemplate.Triggers>
        <Trigger Property="IsSelected" Value="true">
            <Setter Property="Foreground" Value="Green"/>
            <Setter Property="Background" Value="Black"/>
        </Trigger>                            
        <Trigger Property="IsEnabled" Value="false">
            <Setter Property="Foreground" Value="Purple"/>
            <Setter Property="Background" Value="White"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>