WPF 的简单关闭按钮
一个小型且简单的 cross 按钮,用于您的 WPF 应用程序。
引言
在本文中,我将向您展示如何创建一个非常简单的控件来表示一个小型的 cross 按钮 - 类似于您在选项卡式窗口或某些控件中看到的那种。
背景
我发现,在创建一个允许用户使用小按钮关闭选项卡的自定义选项卡控件时,这样的控件会很有用。然而,在后来的项目中,这个小型控件出乎意料地具有多功能性。
创建自定义控件
让我们开始吧。创建一个新的 Visual Studio 解决方案,并向其添加一个 WPF 自定义控件库。自定义控件代码非常简单
/// <summary>
/// The Cross Button is a very simple version
/// of the button that displays as a discrete cross,
/// similar to the buttons at the top of Google Chrome's tabs.
/// </summary>
public class CrossButton : Button
{
/// <summary>
/// Initializes the <see cref="CrossButton"/> class.
/// </summary>
static CrossButton()
{
// Set the style key, so that our control template is used.
DefaultStyleKeyProperty.OverrideMetadata(typeof(CrossButton),
new FrameworkPropertyMetadata(typeof(CrossButton)));
}
}
现在我们将控件派生自 Button
;这段代码真正做的唯一事情是确保我们用于 CrossButton
的样式是正确的样式,我们将在我们的 Generic.xaml 字典中添加该样式。
实际上,我们在控件中没有自定义代码 - 我们可以将整个东西定义为一个样式,该样式只是重新模板化按钮。但是,在我的本地版本中,我添加了一些更多的功能 - 如果您有一个像这样的类,您也可以扩展您的类。
XAML
Generic.xaml 文件中的 XAML 也很基本
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CrossButton">
<Style TargetType="{x:Type local:CrossButton}">
Generic.xaml 是一个资源字典,我们需要一个对我们在控件中定义的命名空间的引用。我们在资源字典中唯一拥有的是 cross 按钮的样式。
注意:如果您想简单地将此控件实现为样式,只需将目标类型设置为“Button
”并给样式一个键 - 然后将该样式应用于任何按钮。
继续,我们将需要一些按钮的资源。
<!-- Brushes we use for the control. -->
<Style.Resources>
<SolidColorBrush x:Key="NormalBackgroundBrush" Color="#00000000" />
<SolidColorBrush x:Key="NormalBorderBrush" Color="#FFFFFFFF" />
<SolidColorBrush x:Key="NormalForegroundBrush" Color="#FF8f949b" />
<SolidColorBrush x:Key="HoverBackgroundBrush" Color="#FFc13535" />
<SolidColorBrush x:Key="HoverForegroundBrush" Color="#FFf9ebeb" />
<SolidColorBrush x:Key="PressedBackgroundBrush" Color="#FF431e20" />
<SolidColorBrush x:Key="PressedBorderBrush" Color="#FF110033" />
<SolidColorBrush x:Key="PressedForegroundBrush" Color="#FFf9ebeb" />
</Style.Resources>
这些是我们将用于在按钮的各种状态下绘制按钮的画笔。
<!-- Simple properties that we set. -->
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Focusable" Value="False" />
这是一个很小的按钮,将光标设置为手形会有助于表明它是可点击的。此外,通过将 Focusable
样式设置为 False
,我们阻止用户通过 tab 键切换到控件,这在大多数情况下会有点奇怪。
这里变得更有趣了
<!-- The control template. -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
在这里,我们将更改控件的模板。控件模板用于绘制控件 - 通过更改模板,我们可以完全更改绘制控件的方式。
<Grid Background="Transparent">
<!-- The background of the button, as an ellipse. -->
<Ellipse x:Name="backgroundEllipse" />
<!-- A path that renders a cross. -->
<Path x:Name="ButtonPath"
Margin="3"
Stroke="{StaticResource NormalForegroundBrush}"
StrokeThickness="1.5"
StrokeStartLineCap="Square"
StrokeEndLineCap="Square"
Stretch="Uniform"
VerticalAlignment="Center"
HorizontalAlignment="Center">
cross 按钮是一个外观简单的按钮 - 一个小 cross,当鼠标悬停在其上时,后面有一个红色圆圈。我们将椭圆和路径(将绘制 cross)放在一个网格中,一个绘制在另一个之上。
我们有路径,但我们需要定义它的几何图形
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="0,0">
<LineSegment Point="25,25"/>
</PathFigure>
<PathFigure StartPoint="0,25">
<LineSegment Point="25,0"/>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Grid>
几何图形非常简单 - 两条线段!我们可以关闭路径和网格,现在转向更具交互性的功能。我们将使用触发器来更改颜色,因为鼠标在控件上移动。
<!-- The triggers. -->
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="backgroundEllipse" Property="Fill"
Value="{StaticResource HoverBackgroundBrush}" />
<Setter TargetName="ButtonPath" Property="Stroke"
Value="{StaticResource HoverForegroundBrush}"/>
</Trigger>
当鼠标移动到上方时,第一个触发器被触发 - 简单地更改背景椭圆和按钮路径的颜色。
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
如果控件未启用,我们将隐藏它 - 这是一个非常不显眼的小按钮。
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="backgroundEllipse" Property="Fill"
Value="{StaticResource PressedBackgroundBrush}" />
<Setter TargetName="backgroundEllipse" Property="Stroke"
Value="{StaticResource PressedBorderBrush}" />
<Setter TargetName="ButtonPath" Property="Stroke"
Value="{StaticResource PressedForegroundBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
我们使用最后一个触发器在按下时将控件着色为黑色和白色。在此之后,我们关闭所有标签,我们就完成了字典。
示例
示例应用程序展示了如何在数据模板中使用该控件从列表中删除项目
这只是该控件的一种用法 - 下面是另一种(不在示例中)
如果有人觉得上面的控件有用,请告诉我,我将撰写一篇关于它的文章。