x:Key="{x:Type TextBox}"是什么意思?

16

标题已经说得很清楚了:

我已经多次阅读到这样设置样式的建议:

<Style TargetType="TextBox">...</Style>

大致相当于:

<Style x:Key="{x:Type TextBox}" TargetType="TextBox">...</Style>

(上一次在对另一个问题的评论中

两者都应该将样式应用于应用程序中的所有textBox(如果它们被放置在应用程序的资源中当然)

但我在我的应用程序中尝试了两个,只有定义了x:Key的第二个才有效。

对我来说,这似乎很合理,因为第一个没有设置任何x:Key属性,不知道应该应用在哪里,但是第一个语法的意义是什么?

编辑:我应用程序中的代码示例工作正常:

<Style x:Key="{x:Type ComboBoxItem}" TargetType="{x:Type ComboBoxItem}">
     <Setter Property="HorizontalContentAlignment" Value="Left"/>
     <Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>

而不是代码:

<Style TargetType="{x:Type ComboBoxItem}">
     <Setter Property="HorizontalContentAlignment" Value="Left"/>
     <Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>

我写这篇文章是为了解决当你操作现有ComboBox的itemsSource时,comboBoxItems会出现绑定问题。第一段代码可以正常工作,但第二段代码不行。

如果将horizontalContentAlignment设置为Right,您可以轻松地看到这一点。

编辑2: 这段代码只是放在我的App.xaml的资源字典中。用TargetType =“ComboBoxItem”替换TargetType =“{x:Type ComboBoxItem}”没有任何区别。

编辑3: 我刚刚意识到可能忘记了说明一些重要的事情(对此很抱歉):虽然样式是在xaml中定义的,但我实际上在我的代码后台将控件添加到布局中,因为它们是动态添加的。这可能是问题所在...

4个回答

10
如上面的第一个例子所示, 将TargetType属性设置为 TextBlock而不分配样式 带有x:Key,允许您的样式 应用于所有TextBlock元素。 实际发生的是这样 隐含地将x:Key设置为{x:Type TextBlock}。这也意味着如果 您给样式一个不同于{x:Type的x:Key TextBlock}的值, 该样式不会自动应用于所有TextBlock元素。 相反,您需要显式地应用样式到TextBlock元素。

考虑到这是来自官方文档,您的问题必须是异类。我见过一些这样的奇怪现象,它们并不是太出乎意料,因为WPF背后的编码肯定是不完美的。

(如果省略密钥,则TargetType="ComboBoxItem"TargetType="{x:Type ComboBoxItem}"之间是否存在结果差异?)


你能详细说明一下你在这里所说的意思吗:“因为WPF背后的编码注定是不完美的。” 你认为这种情况是WPF中的一个bug吗?在我们得出结论之前,我认为我们需要看到更多的代码。 - Øyvind Bråthen
你认为这个情况是WPF中的一个bug吗?是的,这正是我的意思。我认为你不需要更多的代码来得出这个结论,因为我们有一个应该发生什么的描述和一个报告,事实上并不总是这样。提供的代码似乎非常简单,如果其他所有东西都完全相同,那么你可以得出结论,故障必须与核心WPF代码有关。 - H.B.
这句话的意思是,您可以将TargetType属性与x:Type属性结合使用。然后,只有当ComboBoxItem显式地在XAML中设置时,您的样式才会应用。 - Phil Gan
我将这个标记为正确答案,因为我现在确信它一定是这样的。我确实创建了一个新的测试项目来尝试你们所有人写的东西,基本上你们都是对的:我得到了我应该得到的东西。现在,我确定这在我的主项目中不像在我的测试项目中那样工作。必须有某些东西触发了“错误”的行为,但我找不到原因。这与我的样式声明方式无关,因为我在我的测试应用程序中声明它们的方式与我在我的主应用程序中声明它们的方式完全相同。 - David
如果省略了键值,TargetType="ComboBoxItem"TargetType="{x:Type ComboBoxItem}"之间的结果有什么区别吗? - Rui Monteiro
1
@RuiMonteiro:不应该有问题,因为属性的类型是“Type”,转换应该自动进行,无需使用“{x:Type}”。 - H.B.

5
现在,您可以通过添加一个“:”来级联您的样式:
BasedOn="{StaticResource {x:Type ComboBox}}"

在文档的较低位置进一步使用<Style/>,例如:
<Window.Resources>
     <Style x:Key="{x:Type TextBox}" TargetType="{x:Type TextBox}">
          <Setter Property="HorizontalContentAlignment" Value="Left"/>
          <Setter Property="VerticalContentAlignment" Value="Center"/>
      </Style>
</Window.Resources>
<StackPanel>
    <TextBox>I'm Left-Center</TextBox>
    <Grid>
        <Grid.Resources>
           <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
                <Setter Property="HorizontalContentAlignment" Value="Right"/>
            </Style>
        <Grid.Resources>
        <TextBox>I'm Right-Center</TextBox>
    </Grid>
</StackPanel>

不知道这个语法,有趣!但是并没有真正说明 x:key="{x:type xxx}" 是做什么的。 - David
你的示例在没有 x:Key 的情况下也可以工作,因此在这里并不是很相关。 - Nicolas
为什么不使用 TargetType="TextBox" 呢? - Rui Monteiro

3
每个资源都需要一个键,但如果样式中省略了“Key”,它应默认为TargetType的类型。因此,您上面的两个代码片段应该是等效的。
你能否发布整个代码,在没有显式指定Key定义时无法工作的地方?

此外,在您的无效示例中,请尝试将TargetType = "{x:Type ComboBoxItem}替换为TargetType ="ComboBoxItem"。 - Øyvind Bråthen
我又编辑了我的问题,并回答了你的问题:我真的很困惑。也许我的应用程序代码的其他部分会干扰wpf的行为方式,但我不打算检查我添加的每个单独的comboBox,因为这需要太长时间,而且我可以接受设置x:Key。这只是出于好奇... - David
我看到了你的第三次编辑,我认为这在某种程度上是原因。但这并不能解释为什么当你明确设置x:Key时它能够工作。也许隐式键是XAML解析器处理的内容,并且不适用于以编程方式添加的控件,而显式键定义则适用,但这只是我的猜测。一个有趣的案例! - Øyvind Bråthen

0
在WPF XAML中,TargetType="TextBox"TargetType="{x:Type TextBox}"都是有效且等效的。 x:Type标记扩展用于指定Type对象的值。在这种情况下,它指定了类型TextBox。它通常用于XAML中指定控件的类型,例如在样式或数据触发器的TargetType属性中。
使用TargetType="TextBox"是WPF提供的一种快捷方式,以简化最常用场景的标记。此语法隐式创建了TextBox类型的TypeExtension
因此,TargetType="TextBox"TargetType="{x:Type TextBox}"将具有相同的结果,即将TextBox类型指定为样式或数据触发器的目标类型。

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