WPF自定义控件 按钮 (二)

2017-09-19 20:38:55来源:CSDN作者:sudazf人点击

分享
第七城市

上一篇介绍了如何使用阿里巴巴图标和制作带图标的按钮,前面的做法只是简单介绍,要真正能够运用到项目中,还有一段路要走,这里继续介绍如何完善之前的自定义按钮,使之能够合理的运用到以后的项目中。

就拿上一个测试代码来说:

<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="&#xe6f0;" FontSize="50" Foreground="Green" Style="{StaticResource MyIcon}" ></TextBlock>    </Grid></Window>


一个真正的项目中,可能会需要几十种按钮图标,如果遇到这样的情况,在上面的代码中,只能改改 Content 这些现成的属性值,是没法在前台直接去改掉微信图标的;有人想到可以多建一些button模板,可以是可以的,就是太不人性化了;


接下来介绍一种方式,能够在前台设置各种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="&#xe7d6;" Background="Orange" />        <TextBlock Grid.Row="1" Grid.Column="0" Text="&#xe6f0;" FontSize="50" Foreground="Green" Style="{StaticResource MyIcon}" ></TextBlock>        <controls:MyButton1  Grid.Row="1" Grid.Column="1" Width="100" Height="50" Content="MyButton1" MyIcon="&#xe6ea;" 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="&#xe7d6;" MyIconMargin="3" MyIconSize="25" Foreground="Green"  Background="Orange" />        <TextBlock Grid.Row="1" Grid.Column="0" Text="&#xe6f0;" FontSize="50" Foreground="Green" Style="{StaticResource MyIcon}" ></TextBlock>        <controls:MyButton1  Grid.Row="1" Grid.Column="1" Width="100" Height="50" Content="MyButton1" MyIcon="&#xe6ea;" 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="&#xe7d6;" MyIconMargin="3" MyIconSize="25" Foreground="Green"  Background="Orange" />        <TextBlock Grid.Row="1" Grid.Column="0" Text="&#xe6f0;" FontSize="50" Foreground="Green" Style="{StaticResource MyIcon}" ></TextBlock>        <controls:MyButton1  Grid.Row="1" Grid.Column="1" Width="100" Height="50" Content="MyButton1" MyIcon="&#xe6ea;" MyIconMargin="4" MyIconSize="30" Foreground="White" Background="Orange" />        <controls:MyButton1  Grid.Row="2" Grid.Column="0" Style="{StaticResource RoundButton}" Width="80" MyIcon="&#xe6f0;" Height="80" MyIconMargin="25,-15,0,0" MyIconSize="30" Foreground="White"  />    </Grid></Window>


效果如下:


以上仅仅介绍了附加属性+样式模板的使用,鼠标经过+鼠标点击等效果还没有做,下一篇介绍如何制作鼠标经过+点击效果动画。

第七城市

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台