滑块效果演示如图:
源码下载地址
直接贴源码,有帮助的话求点个赞,不过分吧:
【MainWindow.Xaml】
<Window
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:WPF_Test2"
x:Class="WPF_Test2.MainWindow"
mc:Ignorable="d" x:Name="mwindow"
Title="MainWindow" Height="350" Width="525" Background="LightBlue">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<local:Switcher Grid.Column="0" />
<local:Switcher Grid.Column="1" Height="60" Width="160" FontSize="28" Foreground="Red" IsChecked="True"
BorderThickness="1" BorderBrush="Yellow" CheckedTip=" 开" UncheckedTip="关 "
BallColor="Red" Checked="sw_Checked" Unchecked="sw_Unchecked"/>
</Grid>
</Window>
【 Generic.Xaml】
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPF_Test2">
<local:HeightCornerRadiusConverter x:Key="hcrConverter"/>
<local:CheckedToHidenConvert x:Key="CheckedToHidenConvert"/>
<local:CheckedToVisbilityConvert x:Key="CheckedToVisbilityConvert"/>
<Style x:Name="SwitcherStyle" TargetType="{x:Type local:Switcher}">
<Setter Property="Height" Value="40"/>
<Setter Property="Width" Value="90"/>
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="BorderBrush" Value="White"/>
<Setter Property="Background" Value="#ff212c7e"/>
<Setter Property="IsChecked" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Switcher}">
<Border x:Name="bd1" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="{TemplateBinding ActualHeight ,Converter={StaticResource hcrConverter}}"
Background="{TemplateBinding Background}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="1">
<Grid x:Name="gd1">
<Ellipse x:Name="e1" Grid.Column="0" Fill="{TemplateBinding BallColor}" Width="{Binding ActualHeight, RelativeSource={RelativeSource Mode=Self}}"
Panel.ZIndex="1" Grid.ColumnSpan="2">
<UIElement.RenderTransform>
<TranslateTransform X="0" x:Name="trans"/>
</UIElement.RenderTransform>
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Margin" Value="0,3"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Margin" Value="0,2"/>
</Trigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<TextBlock x:Name="cTip" Margin="4,2" VerticalAlignment="Center" HorizontalAlignment="Left"
Text="{TemplateBinding CheckedTip}" Visibility="{TemplateBinding IsChecked,Converter={StaticResource CheckedToHidenConvert}}"/>
<TextBlock x:Name="unTip" Margin="4,2" VerticalAlignment="Center" HorizontalAlignment="Right"
Text="{TemplateBinding UncheckedTip}" Visibility="{TemplateBinding IsChecked,Converter={StaticResource CheckedToVisbilityConvert}}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="IsChecked" Value="False"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background" Value="LightGray"/>
</MultiTrigger.Setters>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="IsChecked" Value="True"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background" Value="#ff546ab3"/>
</MultiTrigger.Setters>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="False"/>
<Condition Property="IsChecked" Value="False"/>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background" Value="Gray"/>
</MultiTrigger.Setters>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
【Switcher.cs】
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace WPF_Test2
{
public class Switcher : ToggleButton
{
private System.Windows.Media.TranslateTransform ballMoveX;
static Switcher()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Switcher), new FrameworkPropertyMetadata(typeof(Switcher)));
}
#region Propdp
public static readonly DependencyProperty CheckedTipProperty =
DependencyProperty.Register("CheckedTip", typeof(string), typeof(Switcher), new PropertyMetadata("ON"));
public static readonly DependencyProperty UncheckedTipProperty =
DependencyProperty.Register("UncheckedTip", typeof(string), typeof(Switcher), new PropertyMetadata("OFF"));
public static readonly DependencyProperty BallColorProperty =
DependencyProperty.Register("BallColor", typeof(Brush), typeof(Switcher), new PropertyMetadata(new SolidColorBrush(Colors.White)));
public string CheckedTip
{
get { return (string)GetValue(CheckedTipProperty); }
set { SetValue(CheckedTipProperty, value); }
}
public string UncheckedTip
{
get { return (string)GetValue(UncheckedTipProperty); }
set { SetValue(UncheckedTipProperty, value); }
}
public Brush BallColor
{
get { return (Brush)GetValue(BallColorProperty); }
set { SetValue(BallColorProperty, value); }
}
#endregion
public Switcher() : base()
{
Checked += CheckedAnimation;
Unchecked += UncheckedAnimation;
Loaded += (e, s) =>
{
ballMoveX = ((Switcher)e).GetTemplateChild("trans") as System.Windows.Media.TranslateTransform;
if (IsChecked != null) ballMoveX.X = (IsChecked == true ? -1 : 1) * (ActualWidth - ActualHeight) / 2;
};
}
#region Animations
DoubleAnimation ballAnima = new DoubleAnimation(0, new Duration(new TimeSpan(0, 0, 0, 0, 300)))
{
EasingFunction = new CubicEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut }
};
private void CheckedAnimation(object sender, RoutedEventArgs e)
{
if (!IsLoaded) e.Handled = true;//未初始化成功时,不向外传递Checked事件
if (ballMoveX == null) return;
ballAnima.To = -(ActualWidth - ActualHeight) / 2;
ballMoveX.BeginAnimation(System.Windows.Media.TranslateTransform.XProperty, ballAnima);
}
private void UncheckedAnimation(object sender, RoutedEventArgs e)
{
if (!IsLoaded) e.Handled = true;//未初始化成功时,不向外传递Unchecked事件
if (ballMoveX == null) return;
ballAnima.To = (ActualWidth - ActualHeight) / 2;
ballMoveX.BeginAnimation(System.Windows.Media.TranslateTransform.XProperty, ballAnima);
}
#endregion
}
#region Converters
/// <summary>
/// 根据控件高度设置控件圆角半径
/// 圆角半径为高度的二分之一
/// </summary>
public class HeightCornerRadiusConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return 0.5 * int.Parse(value.ToString());
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
/// <summary>
/// 当Ischecked=True时,
/// 隐藏CheckedTip文本
/// </summary>
public class CheckedToVisbilityConvert : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return Visibility.Hidden;
return (bool)value ? Visibility.Visible : Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
/// <summary>
/// 当Ischecked=False时,
/// 隐藏UncheckedTip文本
/// </summary>
public class CheckedToHidenConvert : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return Visibility.Hidden;
return (bool)value ? Visibility.Hidden : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
#endregion
}