在样式中更改按钮的内容?

17

我正在尝试做类似于这个的事情:

<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Grid>
        <Button>
            <Button.Style>
                <Style TargetType="{x:Type Button}">
                    <Setter Property="Content"
                            Value="No mouse over" />
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver"
                                 Value="True">
                            <Setter Property="Content">
                                <Setter.Value>
                                    <CheckBox Content="Mouse is over" />
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
    </Grid>
</Window>

但是,我遇到了一个运行时的XamlParseException,错误信息如下:

无法将内容类型为'System.Windows.Controls.CheckBox'的内容添加到类型为'System.Object'的对象中。对象错误为'System.Windows.Controls.CheckBox'。

我实际上正在尝试根据外部条件为按钮的内容绘制不同的图标。因此,我正在尝试使用DataTrigger,但上面的示例简化了问题。有什么想法吗?

4个回答

39

实际错误是由于无法将Visuals直接设置为Setter值所导致。 但是,您可以通过使用DataTemplate设置ContentTemplate或通过创建作为资源的内容(可以是特定于按钮或位于其他位置)来获取您正在寻找的行为。

<Button>
    <Button.Resources>
        <CheckBox x:Key="Local_MouseOverContent" Content="Mouse is over" />
    </Button.Resources>
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Content" Value="No mouse over" />
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Content"
                            Value="{StaticResource Local_MouseOverContent}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

<Button>
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Setter Property="Content" Value="No mouse over" />
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate DataType="Button">
                                <CheckBox Content="Mouse is over" />
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

6

注意!你的示例在.NET Framework 4中可以正常工作,无需进行任何更改!!!

  <Button>
        <Button.Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Content"
                        Value="No mouse over" />
                <Style.Triggers>
                    <Trigger Property="IsMouseOver"
                             Value="True">
                        <Setter Property="Content">
                            <Setter.Value>
                                <CheckBox Content="Mouse is over" />
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
    </Button>

这真的很有效,谢谢!但是当使用属性设置Button.Content属性时,它就不起作用了。例如:<Button Content="initial content" Style="{StaticResource StyleChangeContentOnMouseOver}" /> 只会显示 "initial content" - FlyingFoX

2

如果您正在创建一个通用样式,以供应用程序中的所有按钮使用,那么如果图像是一种资源,您将会遇到视觉树冲突。因此,在这种情况下,模板是您唯一的选择。


-1

警告:这可能不是最好或正确的方法。确保您也阅读了本页面上的其他答案。

在这种情况下,您肯定想要使用控件模板。类似于:


<style>
    <Setter Property="Content">
        <Setter.Value>
            <ControlTemplate>
                <Image Img="something.jpg" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</style>

并在触发器中添加一个控件模板以进行悬停。

这里有一个好的链接


1
这不是有效的方法。ControlTemplate 用于修改控件的视觉结构和行为,而不是它的内容。此外,ContentProperty 无法呈现 ControlTemplate,除非您还设置了 ContentTemplate。 - rmoore
3
正如 Moore 所说,这样是行不通的。你需要将 ContentTemplate 属性设置为 DataTemplate。 - Wilka
2
抱歉,我曾经给你投了反对票,但现在 Stack Overflow 不允许我取消。我已经阅读了你指向的那篇文章,看起来 ControlTemplate 可以被设置为控件的内容,但这似乎有些奇怪。另外,你也非常明确地指出这可能不是最优解决方案。 - jpierson
@jpierson 这篇文章还不错,但解决方案确实不太优化。我为了支持它投了+1;毕竟这是一个不同的解决方案,但它确实可行。 - Malavos

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