上一篇介绍了如何使用阿里巴巴图标和制作带图标的按钮,前面的做法只是简单介绍,要真正能够运用到项目中,还有一段路要走,这里继续介绍如何完善之前的自定义按钮,使之能够合理的运用到以后的项目中。
就拿上一个测试代码来说:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:controls="clr-namespace:WpfCustomControlLibrary.Controls;assembly=WpfCustomControlLibrary"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Content="Default Button" Width="100" Height="50"></Button>
<controls:MyButton1 Grid.Row="0" Grid.Column="1" Width="100" Height="50" Content="MyButton1" Background="Orange" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="" FontSize="50" Foreground="Green" Style="{StaticResource MyIcon}" ></TextBlock>
</Grid>
</Window>
接下来介绍一种方式,能够在前台设置各种Icon,就是使用 附加属性:
1.修改 MyButton1.cs 代码为:
public class MyButton1 : Button
{
static MyButton1()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyButton1), new FrameworkPropertyMetadata(typeof(MyButton1)));
}
public static readonly DependencyProperty MyIconProperty =
DependencyProperty.Register("MyIcon", typeof(string), typeof(MyButton1), new PropertyMetadata("\ue6f0"));
/// <summary>
/// 按钮字体图标编码
/// </summary>
public string MyIcon
{
get { return (string)GetValue(MyIconProperty); }
set { SetValue(MyIconProperty, value); }
}
}
2.修改 MyButton1.xaml 样式代码为:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCustomControlLibrary.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WpfCustomControlLibrary;component/Controls/MyIcon.xaml" />
</ResourceDictionary.MergedDictionaries>
<ControlTemplate x:Key="MyButton1_Template" TargetType="{x:Type local:MyButton1}">
<Border x:Name="border" Background="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= Background}"
Height="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Height}"
CornerRadius="2"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Width="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Width}">
<!--Icon/Text-->
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
<TextBlock x:Name="icon" Margin="3"
RenderTransformOrigin="0.5,0.5" Style="{StaticResource MyIcon}"
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= MyIcon}"
FontSize="30"
Foreground="Green">
<TextBlock.RenderTransform>
<RotateTransform x:Name="transIcon" Angle="0"/>
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock VerticalAlignment="Center" x:Name="txt"
TextDecorations="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ContentDecorations}"
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}" />
</StackPanel>
</Border>
</ControlTemplate>
<Style TargetType="{x:Type local:MyButton1}">
<Setter Property="Template" Value="{StaticResource MyButton1_Template}"/>
</Style>
</ResourceDictionary>
实际上就改了一行代码:
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= MyIcon}"
3.修改测试程序前端代码:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:controls="clr-namespace:WpfCustomControlLibrary.Controls;assembly=WpfCustomControlLibrary"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Content="Default Button" Width="100" Height="50"></Button>
<controls:MyButton1 Grid.Row="0" Grid.Column="1" Width="100" Height="50" Content="MyButton1" MyIcon="" Background="Orange" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="" FontSize="50" Foreground="Green" Style="{StaticResource MyIcon}" ></TextBlock>
<controls:MyButton1 Grid.Row="1" Grid.Column="1" Width="100" Height="50" Content="MyButton1" MyIcon="" Background="Orange" />
</Grid>
</Window>
这样就能在前台修改任意的icon了:
当然,仅仅能够修改icon还是远远不够的,;还有icon大小,颜色,边距等都要能够在前台自由设置,所以需要添加的附加依赖属性还有很多,这就要看具体要求了,这里继续为它添加几个附加属性,包括:icon大小,边距 这2个;(颜色属性一般可以直接使用Button自带的 Foreground 即可)
1.修改 MyButton1.cs 代码:
public class MyButton1 : Button
{
static MyButton1()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyButton1), new FrameworkPropertyMetadata(typeof(MyButton1)));
}
public static readonly DependencyProperty MyIconProperty =
DependencyProperty.Register("MyIcon", typeof(string), typeof(MyButton1), new PropertyMetadata("\ue6f0"));
/// <summary>
/// 按钮字体图标编码
/// </summary>
public string MyIcon
{
get { return (string)GetValue(MyIconProperty); }
set { SetValue(MyIconProperty, value); }
}
public static readonly DependencyProperty MyIconSizeProperty =
DependencyProperty.Register("MyIconSize", typeof(int), typeof(MyButton1), new PropertyMetadata(20));
/// <summary>
/// 按钮字体图标大小
/// </summary>
public int MyIconSize
{
get { return (int)GetValue(MyIconSizeProperty); }
set { SetValue(MyIconSizeProperty, value); }
}
public static readonly DependencyProperty MyIconMarginProperty = DependencyProperty.Register(
"MyIconMargin", typeof(Thickness), typeof(MyButton1), new PropertyMetadata(new Thickness(0, 1, 3, 1)));
/// <summary>
/// 字体图标间距
/// </summary>
public Thickness MyIconMargin
{
get { return (Thickness)GetValue(MyIconMarginProperty); }
set { SetValue(MyIconMarginProperty, value); }
}
}
2.修改 MyButton1.xaml 代码:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCustomControlLibrary.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WpfCustomControlLibrary;component/Controls/MyIcon.xaml" />
</ResourceDictionary.MergedDictionaries>
<ControlTemplate x:Key="MyButton1_Template" TargetType="{x:Type local:MyButton1}">
<Border x:Name="border" Background="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= Background}"
Height="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Height}"
CornerRadius="2"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Width="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Width}">
<!--Icon/Text-->
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
<TextBlock x:Name="icon"
Margin="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=MyIconMargin}"
FontSize="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= MyIconSize}"
Foreground="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= Foreground}"
RenderTransformOrigin="0.5,0.5" Style="{StaticResource MyIcon}"
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= MyIcon}"
>
<TextBlock.RenderTransform>
<RotateTransform x:Name="transIcon" Angle="0"/>
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock VerticalAlignment="Center" x:Name="txt"
TextDecorations="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ContentDecorations}"
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}" />
</StackPanel>
</Border>
</ControlTemplate>
<Style TargetType="{x:Type local:MyButton1}">
<Setter Property="Template" Value="{StaticResource MyButton1_Template}"/>
</Style>
</ResourceDictionary>
3.测试代码:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:controls="clr-namespace:WpfCustomControlLibrary.Controls;assembly=WpfCustomControlLibrary"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Content="Default Button" Width="100" Height="50"></Button>
<controls:MyButton1 Grid.Row="0" Grid.Column="1" Width="100" Height="50" Content="MyButton1" MyIcon="" MyIconMargin="3" MyIconSize="25" Foreground="Green" Background="Orange" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="" FontSize="50" Foreground="Green" Style="{StaticResource MyIcon}" ></TextBlock>
<controls:MyButton1 Grid.Row="1" Grid.Column="1" Width="100" Height="50" Content="MyButton1" MyIcon="" MyIconMargin="4" MyIconSize="30" Foreground="White" Background="Orange" />
</Grid>
</Window>
效果如下:
有了这两个附加属性之后,还可以结合 WPF自定义控件 按钮 (一)中的圆形按钮,做成带图标的圆形按钮,只需要:
1)在 MyButton1.xaml 中新增一个 key 为 RoundButton 的 Style :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCustomControlLibrary.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WpfCustomControlLibrary;component/Controls/MyIcon.xaml" />
</ResourceDictionary.MergedDictionaries>
<ControlTemplate x:Key="MyButton1_Template" TargetType="{x:Type local:MyButton1}">
<Border x:Name="border" Background="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= Background}"
Height="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Height}"
CornerRadius="2"
BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Width="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Width}">
<!--Icon/Text-->
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
<TextBlock x:Name="icon"
Margin="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=MyIconMargin}"
FontSize="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= MyIconSize}"
Foreground="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= Foreground}"
RenderTransformOrigin="0.5,0.5" Style="{StaticResource MyIcon}"
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= MyIcon}"
>
<TextBlock.RenderTransform>
<RotateTransform x:Name="transIcon" Angle="0"/>
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock VerticalAlignment="Center" x:Name="txt"
TextDecorations="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ContentDecorations}"
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}" />
</StackPanel>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="MyButton1_RountTemplate" TargetType="{x:Type local:MyButton1}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition From="Normal" GeneratedDuration="0:0:0.3" To="MouseOver"/>
<VisualTransition From="MouseOver" GeneratedDuration="0:0:0.3" To="Normal"/>
<VisualTransition From="Pressed" GeneratedDuration="0:0:0.2" To="Normal"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="ellipse">
<EasingColorKeyFrame KeyTime="0" Value="#FFEFE9F0"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="ellipse">
<EasingColorKeyFrame KeyTime="0" Value="#FF650A6E"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse x:Name="ellipse" Stroke="Black">
<Ellipse.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#FFF376FF" Offset="0.566"/>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<!--Icon/Text-->
<Canvas VerticalAlignment="Center"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
<TextBlock x:Name="icon"
Margin="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=MyIconMargin}"
FontSize="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= MyIconSize}"
Foreground="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= Foreground}"
RenderTransformOrigin="0.5,0.5" Style="{StaticResource MyIcon}"
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path= MyIcon}"
>
<TextBlock.RenderTransform>
<RotateTransform x:Name="transIcon" Angle="0"/>
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock VerticalAlignment="Center" x:Name="txt"
TextDecorations="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=ContentDecorations}"
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Content}" />
</Canvas>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True"/>
<Trigger Property="IsDefaulted" Value="True"/>
<Trigger Property="IsMouseOver" Value="True"/>
<Trigger Property="IsPressed" Value="True"/>
<Trigger Property="IsEnabled" Value="False"/>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style TargetType="{x:Type local:MyButton1}">
<Setter Property="Template" Value="{StaticResource MyButton1_Template}"/>
</Style>
<Style x:Key="RoundButton" TargetType="{x:Type local:MyButton1}">
<Setter Property="Template" Value="{StaticResource MyButton1_RountTemplate}"/>
</Style>
</ResourceDictionary>
2.在测试项目 App.xaml 中增加 MyButton1.xaml 的引用:
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/WpfCustomControlLibrary;component/Controls/MyIcon.xaml"/>
<ResourceDictionary Source="pack://application:,,,/WpfCustomControlLibrary;component/Controls/MyButton1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
3.修改测试代码:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:controls="clr-namespace:WpfCustomControlLibrary.Controls;assembly=WpfCustomControlLibrary"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Content="Default Button" Width="100" Height="50"></Button>
<controls:MyButton1 Grid.Row="0" Grid.Column="1" Width="100" Height="50" Content="MyButton1" MyIcon="" MyIconMargin="3" MyIconSize="25" Foreground="Green" Background="Orange" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="" FontSize="50" Foreground="Green" Style="{StaticResource MyIcon}" ></TextBlock>
<controls:MyButton1 Grid.Row="1" Grid.Column="1" Width="100" Height="50" Content="MyButton1" MyIcon="" MyIconMargin="4" MyIconSize="30" Foreground="White" Background="Orange" />
<controls:MyButton1 Grid.Row="2" Grid.Column="0" Style="{StaticResource RoundButton}" Width="80" MyIcon="" Height="80" MyIconMargin="25,-15,0,0" MyIconSize="30" Foreground="White" />
</Grid>
</Window>
以上仅仅介绍了附加属性+样式模板的使用,鼠标经过+鼠标点击等效果还没有做,下一篇介绍如何制作鼠标经过+点击效果动画。