按钮自定义内容在运行时不呈现

Buttons custom content is not rendering at runtime

我有一个 UserControl 托管在 Windows 表单中。在这个 UserControl 中,我有一个 ToolBar,其中有各种按钮:

<ToolBar>
   <Button Content="{StaticResource AllGreenIcon}"/>
   <Button Content="{StaticResource AllRedIcon}"/>
   <Button Content="{StaticResource RedRectangle}"/>
   <Button Content="{StaticResource GreenRectangle}"/>
</ToolBar>

在设计器中看起来是这样的:

问题出在图标由 4 个矩形组成的按钮上。运行时不会为这两个按钮呈现内容。

运行时看起来像这样:

代码为AllGreenIcon

<UserControl.Resources>

<Grid x:Key="AllGreenIcon" Height="16" Width="16" Effect="{StaticResource IconDropShadowEffect}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <ContentControl Content="{StaticResource GreenRectangle}" Margin="0,0,1,1" Grid.Row="0" Grid.Column="0"/>
    <ContentControl Content="{StaticResource GreenRectangle}" Margin="1,0,0,1" Grid.Row="0" Grid.Column="1"/>
    <ContentControl Content="{StaticResource GreenRectangle}" Margin="0,1,1,0" Grid.Row="1" Grid.Column="0"/>
    <ContentControl Content="{StaticResource GreenRectangle}" Margin="1,1,0,0" Grid.Row="1" Grid.Column="1"/>
</Grid>


</UserControl.Resources>

有没有人知道我该如何解决这个问题? 提前致谢!

我通过反复试验设法找到了解决方案。基本上我所做的是用 Rectangle 替换 ContentControl 并为 Rectangle 制作样式。

<LinearGradientBrush x:Key="GreenLinearGradientBrush" EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
    <GradientStop Color="#FF00BD22" Offset="1"/>
    <GradientStop Color="#FF218934"/>
</LinearGradientBrush>

<Style x:Key="GreenRectangleStyle" TargetType="{x:Type Rectangle}">
   <Setter Property="Width" Value="16"/>
   <Setter Property="Height" Value="16"/>
   <Setter Property="Fill" Value="{StaticResource GreenLinearGradientBrush}"/>
   <Setter Property="Effect" Value="{StaticResource IconDropShadowEffect}"/>
</Style>

<Grid x:Key="AllGreenIcon" Height="16" Width="16" Effect="{StaticResource IconDropShadowEffect}">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Rectangle Margin="0,0,1,1" Grid.Row="0" Grid.Column="0" Style="{StaticResource GreenRectangleStyle}"/>
    <Rectangle Margin="1,0,0,1" Grid.Row="0" Grid.Column="1" Style="{StaticResource GreenRectangleStyle}"/>
    <Rectangle Margin="0,1,1,0" Grid.Row="1" Grid.Column="0" Style="{StaticResource GreenRectangleStyle}"/>
    <Rectangle Margin="1,1,0,0" Grid.Row="1" Grid.Column="1" Style="{StaticResource GreenRectangleStyle}"/>
</Grid>

有没有人有更好的解决方案?

编辑:

@Novitchi S 有更好的解决方案,基于他的回答,这里是最终版本:

<Style x:Key="GreenRectangleStyle" TargetType="{x:Type Rectangle}">
    <Setter Property="Width" Value="16"/>
    <Setter Property="Height" Value="16"/>
    <Setter Property="Fill" Value="{StaticResource GreenLinearGradientBrush}"/>
    <Setter Property="Effect" Value="{StaticResource IconDropShadowEffect}"/>
</Style>

<DataTemplate x:Key="GreenRectangle">
    <Rectangle  Style="{StaticResource GreenRectangleStyle}"/>
</DataTemplate>

<DataTemplate x:Key="AllGreenIcon">
    <Grid  Height="16" Width="16" Effect="{StaticResource IconDropShadowEffect}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <ContentControl ContentTemplate="{StaticResource GreenRectangle}" Margin="0,0,1,1" Grid.Row="0" Grid.Column="0"/>
        <ContentControl ContentTemplate="{StaticResource GreenRectangle}" Margin="1,0,0,1" Grid.Row="0" Grid.Column="1"/>
        <ContentControl ContentTemplate="{StaticResource GreenRectangle}" Margin="0,1,1,0" Grid.Row="1" Grid.Column="0"/>
        <ContentControl ContentTemplate="{StaticResource GreenRectangle}" Margin="1,1,0,0" Grid.Row="1" Grid.Column="1"/>
    </Grid>
</DataTemplate>

。 . .

<ToolBar>
    <Button ContentTemplate="{StaticResource AllGreenIcon}"/>
    <Button ContentTemplate="{StaticResource AllRedIcon}"/>
    <Button ContentTemplate="{StaticResource RedRectangle}"/>
    <Button ContentTemplate="{StaticResource GreenRectangle}"/>
</ToolBar>

这个常见问题是由于 WPF(逻辑)要求每个 UIElement 都有一个单亲。在您的情况下,您向资源添加了一个元素 - GreenRectangle,然后您将此元素用作 AllGreenIcon 资源中多个 ContentControlContent。每次将元素连接到可视化树时,它都会更改其父引用,这保证了元素在可视化树中只出现一次。 例如,所有绿色按钮都将使用相同的 GreenRectangle 元素实例。由于每次 GreenRectangle 连接到可视化树时,其父项都会更改,只有最后一个使用 GreenRectange 资源的项目才会实际显示该元素。

总而言之,避免在资源中声明和使用 UIElements。你应该使用 Styles 和 Controltemplates.

注意: 在你的解决方案中,资源中声明的 AllGreenIcon 网格将有同样的问题 - 不能在 UI 中的两个不同地方使用同时。请改用 ContentTemplate

例如:

<Button ContentTemplate="{StaticResource AllGreenIconTemplate}"/>