按钮自定义内容在运行时不呈现
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
资源中多个 ContentControl
的 Content
。每次将元素连接到可视化树时,它都会更改其父引用,这保证了元素在可视化树中只出现一次。
例如,所有绿色按钮都将使用相同的 GreenRectangle
元素实例。由于每次 GreenRectangle
连接到可视化树时,其父项都会更改,只有最后一个使用 GreenRectange
资源的项目才会实际显示该元素。
总而言之,避免在资源中声明和使用 UIElements
。你应该使用 Style
s 和 Controltemplate
s.
注意: 在你的解决方案中,资源中声明的 AllGreenIcon
网格将有同样的问题 - 不能在 UI 中的两个不同地方使用同时。请改用 ContentTemplate
。
例如:
<Button ContentTemplate="{StaticResource AllGreenIconTemplate}"/>
我有一个 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
资源中多个 ContentControl
的 Content
。每次将元素连接到可视化树时,它都会更改其父引用,这保证了元素在可视化树中只出现一次。
例如,所有绿色按钮都将使用相同的 GreenRectangle
元素实例。由于每次 GreenRectangle
连接到可视化树时,其父项都会更改,只有最后一个使用 GreenRectange
资源的项目才会实际显示该元素。
总而言之,避免在资源中声明和使用 UIElements
。你应该使用 Style
s 和 Controltemplate
s.
注意: 在你的解决方案中,资源中声明的 AllGreenIcon
网格将有同样的问题 - 不能在 UI 中的两个不同地方使用同时。请改用 ContentTemplate
。
例如:
<Button ContentTemplate="{StaticResource AllGreenIconTemplate}"/>