结局方案截图:
CustomToggleButton.xaml代码:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Local="clr-namespace:CustomControls"> <Style TargetType="{x:Type Local:CustomToggleButton}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Local:CustomToggleButton}"> <Grid> <VisualStateManager.VisualStateGroups> <VisualStateGroup> <VisualStateGroup.Transitions> <!--transition one--> <VisualTransition GeneratedDuration="0:0:0.5" To="Right"> <Storyboard> <DoubleAnimation Storyboard.TargetName="ToggleTransform" Storyboard.TargetProperty="Angle" To="-90" Duration="0:0:0.3" /> </Storyboard> </VisualTransition> <!--transition two--> <VisualTransition GeneratedDuration="0:0:0.5" To="Left"> <Storyboard> <DoubleAnimation Storyboard.TargetName="ToggleTransform" Storyboard.TargetProperty="Angle" To="90" Duration="0:0:0.3" /> </Storyboard> </VisualTransition> </VisualStateGroup.Transitions> <!--group one--> <VisualState x:Name="Right"> <Storyboard> <DoubleAnimation Storyboard.TargetName="ToggleTransform" Storyboard.TargetProperty="Angle" To="-90" Duration="0:0:0" /> </Storyboard> </VisualState> <!--group two--> <VisualState x:Name="Left"> <Storyboard> <DoubleAnimation Storyboard.TargetName="ToggleTransform" Storyboard.TargetProperty="Angle" To="90" Duration="0:0:0" /> </Storyboard> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CustomCornerRadius}"> <ContentPresenter Content="{TemplateBinding CustomContent}"/> </Border> <ToggleButton x:Name="btnToggle" Width="20" Height="20" RenderTransformOrigin="0.5,0.5" Grid.Row="1"> <ToggleButton.Template> <ControlTemplate> <Grid> <Ellipse Stroke="#FFA9A9A9" Fill="AliceBlue"/> <Path Data="M1,1.5 L4.5,5 8,1.5" Stroke="#FF666666" StrokeThickness="2" HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid> </ControlTemplate> </ToggleButton.Template> <ToggleButton.RenderTransform> <RotateTransform x:Name="ToggleTransform"/> </ToggleButton.RenderTransform> </ToggleButton> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
Generic.xaml代码:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="pack://application:,,,/CustomControls;component/Themes/CustomToggleButton.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary>
CustomToggleButton.cs代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; namespace CustomControls { public class CustomToggleButton : Control { public object CustomContent { get { return (object)GetValue(CustomContentProperty); } set { SetValue(CustomContentProperty, value); } } // Using a DependencyProperty as the backing store for CustomContent. This enables animation, styling, binding, etc... public static readonly DependencyProperty CustomContentProperty = DependencyProperty.Register("CustomContent", typeof(object), typeof(CustomToggleButton), null); public CornerRadius CustomCornerRadius { get { return (CornerRadius)GetValue(CustomCornerRadiusProperty); } set { SetValue(CustomCornerRadiusProperty, value); } } // Using a DependencyProperty as the backing store for CustomCornerRadius. This enables animation, styling, binding, etc... public static readonly DependencyProperty CustomCornerRadiusProperty = DependencyProperty.Register("CustomCornerRadius", typeof(CornerRadius), typeof(CustomToggleButton), null); public bool IsToggle { get { return (bool)GetValue(IsToggleProperty); } set { SetValue(IsToggleProperty, value); } } // Using a DependencyProperty as the backing store for IsToggle. This enables animation, styling, binding, etc... public static readonly DependencyProperty IsToggleProperty = DependencyProperty.Register("IsToggle", typeof(bool), typeof(CustomToggleButton), new PropertyMetadata(false)); static CustomToggleButton() { DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomToggleButton), new FrameworkPropertyMetadata(typeof(CustomToggleButton))); } public override void OnApplyTemplate() { base.OnApplyTemplate(); ToggleButton toggle = GetTemplateChild("btnToggle") as ToggleButton; if (toggle != null) toggle.Click += toggle_Click; GotoState(false); } private void toggle_Click(object sender, RoutedEventArgs e) { IsToggle = !IsToggle; GotoState(true); } private void GotoState(bool flag) { if (!IsToggle) VisualStateManager.GoToState(this, "Left", flag); else VisualStateManager.GoToState(this, "Right", flag); } } }
MainWindow.xaml代码:
<Window x:Class="WpfApp_New3.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" xmlns:CustomControls="clr-namespace:CustomControls;assembly=CustomControls"> <Grid> <CustomControls:CustomToggleButton x:Name="CustomToggle" BorderBrush="DarkOrange" BorderThickness="3" CustomCornerRadius="4"> <CustomControls:CustomToggleButton.CustomContent> <StackPanel Margin="6"> <Button Margin="3" Padding="3" Content="Button One"></Button> <Button Margin="3" Padding="3" Content="Button Two"></Button> <Button Margin="3" Padding="3" Content="Button Three"></Button> <Button Margin="3" Padding="3" Content="Button Four"></Button> </StackPanel> </CustomControls:CustomToggleButton.CustomContent> </CustomControls:CustomToggleButton> </Grid> </Window>