WPF中的下划线标签,使用样式

Bor*_*ris 11 wpf xaml label styles

我有以下风格:

<Style x:Key="ActionLabelStyle" TargetType="{x:Type Label}">
    <Setter Property="Margin" Value="10,3" />
    <Setter Property="Padding" Value="0" />
    <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
    <Setter Property="FontFamily" Value="Calibri" />
    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsMouseOver" Value="True" />
                <Condition Property="IsEnabled" Value="True" />
            </MultiTrigger.Conditions>
            <Setter Property="Background" Value="Red" />
            <Setter Property="TextBlock.TextDecorations" Value="Underline" />
        </MultiTrigger>
    </Style.Triggers>
</Style>
Run Code Online (Sandbox Code Playgroud)

所以基本上,我希望有一个标签,当它被启用并且鼠标光标在它上面时加下划线.这种风格不起作用的部分是<Setter Property="TextBlock.TextDecorations" Value="Underline" />.现在,我在这里做错了什么?谢谢你的帮助.

Jer*_*ard 23

这实际上比它看起来要困难得多.在WPF中,Label不是TextBlock.它派生自ContentControl,因此可以在其Content集合中托管其他非文本控件.

但是,您可以将字符串指定为内容,如下例所示.在内部,将构造一个TextBlock来为您托管文本.

<Label Content="Test!"/>
Run Code Online (Sandbox Code Playgroud)

这内部转换为:

    <Label>
        <Label.Content>
            <TextBlock>
                Test!
            </TextBlock>
        </Label.Content>
    </Label>
Run Code Online (Sandbox Code Playgroud)

对此的简单解决方案是将TextBlock的TextDecorations属性作为附加属性.例如,FontSize是这样设计的,因此以下工作原理:

    <Label TextBlock.FontSize="24">
        <Label.Content>
            <TextBlock>
                Test!
            </TextBlock>
        </Label.Content>
    </Label>
Run Code Online (Sandbox Code Playgroud)

TextBlock.FontSize附加属性可以应用于可视树中的任何位置,并将覆盖树中任何TextBlock后代上该属性的默认值.但是,TextDecorations属性不是这样设计的.

这给你留下了至少一些选择.

  1. 使用颜色,边框,光标等,而不是带下划线的文本,因为这100%更容易实现.
  2. 更改您执行此操作的方式以将样式应用于TextBlock.
  3. 麻烦创建自己的附加属性和控制模板以尊重它.
  4. 执行以下操作来嵌套显示为样式子项的TextBlocks的样式:

仅供参考,这是迄今为止我在WPF中所做过的最丑陋的事情,但它确实有效!

    <Style x:Key="ActionLabelStyle" TargetType="{x:Type Label}">
        <Setter Property="Margin" Value="10,3" />
        <Setter Property="Padding" Value="0" />
        <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
        <Setter Property="FontFamily" Value="Calibri" />
        <Style.Triggers>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsMouseOver" Value="True" />
                    <Condition Property="IsEnabled" Value="True" />
                </MultiTrigger.Conditions>
                <Setter Property="Background" Value="Red" />
            </MultiTrigger>
        </Style.Triggers>
        <Style.Resources>
            <Style TargetType="TextBlock">
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Label}, Path=IsMouseOver}" Value="True" />
                            <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" Value="True" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="TextDecorations" Value="Underline"/>
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </Style.Resources>
    </Style>
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为它覆盖了此样式的Label下面的任何TextBlock的默认样式.然后,它使用MultiDataTrigger允许相对绑定回到Label,以检查其IsMouseOver属性是否为True.呸.

编辑:

请注意,这仅在您显式创建TextBlock时有效.当我发布这个时,我不正确,因为我已经弄脏了我的测试标签.嘘.谢谢,Anvaka,指出这一点.

    <Label Style="{StaticResource ActionLabelStyle}">
        <TextBlock>Test!</TextBlock>
    </Label>
Run Code Online (Sandbox Code Playgroud)

这是有效的,但是如果你不得不去解决这个问题,你只是努力工作.要么有人会发布更聪明的东西,要么就像你说的那样,我的选择1现在看起来很不错.

  • 好答案 :).您不需要在触发器中具有IsEnabled属性.如果它被禁用,则不会收到MouseOver事件.如果您在标签中设置内容,它也将无效:<Label Style ="{StaticResource ActionLabelStyle}"Content ="Hey"/>,所以要小心. (2认同)