WPF中的滑块打开/关闭开关

6tr1vspr  于 2022-11-18  发布在  其他
关注(0)|答案(6)|浏览(306)

我正在寻找一个WPF教程,就像在iPhone上创建一个幻灯片开/关开关。
下面是一个示例(“发送所有流量”选项)https://secure-tunnel.com/support/software_setup/iphone/images/iphone_vpn_settings.jpg

iih3973s

iih3973s1#

我还没有看过关于这个问题的教程,但是我想你可以从启动Expression Blend开始,在它上面放一个复选框。然后选择复选框,进入主菜单-对象-〉编辑样式-〉编辑副本
这将使Blend生成CheckBox的默认样式,以便您能够修改它。看看这里的工作原理,您将能够获得一些结果。
基本上(除了颜色和画笔的东西),你需要查看与IsChecked属性挂钩的触发器。例如,当IsChecked为True时,你将矩形移动到一边,显示ON单词并隐藏OFF单词。要动画化这个,你只需要添加触发器的进出动画。
UPD:我花了10-15分钟的时间来制作一个“原型”:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="CheckBoxIPhone.Window1"
    x:Name="Window"
    Title="Window1"
    Width="320" 
    Height="240" 
    FontFamily="Segoe UI" 
    FontSize="20" 
    WindowStartupLocation="CenterScreen"
    >

    <Window.Resources>
        <Style x:Key="CheckBoxStyle1" TargetType="{x:Type CheckBox}">
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
            <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type CheckBox}">
                        <ControlTemplate.Resources>
                            <Storyboard x:Key="OnChecking">
                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
                                    <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="25"/>
                                </DoubleAnimationUsingKeyFrames>
                            </Storyboard>
                            <Storyboard x:Key="OnUnchecking">
                                <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
                                    <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>
                                </DoubleAnimationUsingKeyFrames>
                                <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(FrameworkElement.Margin)">
                                    <SplineThicknessKeyFrame KeyTime="00:00:00.3000000" Value="1,1,1,1"/>
                                </ThicknessAnimationUsingKeyFrames>
                            </Storyboard>
                        </ControlTemplate.Resources>

                        <DockPanel x:Name="dockPanel">
                            <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplate="{TemplateBinding ContentTemplate}" RecognizesAccessKey="True" VerticalAlignment="Center"/>
                            <Grid Margin="5,5,0,5" Width="50" Background="#FFC0CCD9">
                                <TextBlock Text="ON" TextWrapping="Wrap" FontWeight="Bold" FontSize="12" HorizontalAlignment="Right" Margin="0,0,3,0"/>
                                <TextBlock HorizontalAlignment="Left" Margin="2,0,0,0" FontSize="12" FontWeight="Bold" Text="OFF" TextWrapping="Wrap"/>
                                <Border HorizontalAlignment="Left" x:Name="slider" Width="23" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3" RenderTransformOrigin="0.5,0.5" Margin="1,1,1,1">
                                    <Border.RenderTransform>
                                            <TransformGroup>
                                                <ScaleTransform ScaleX="1" ScaleY="1"/>
                                                <SkewTransform AngleX="0" AngleY="0"/>
                                                <RotateTransform Angle="0"/>
                                                <TranslateTransform X="0" Y="0"/>
                                            </TransformGroup>
                                        </Border.RenderTransform>
                                        <Border.BorderBrush>
                                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                <GradientStop Color="#FFFFFFFF" Offset="0"/>
                                                <GradientStop Color="#FF4490FF" Offset="1"/>
                                            </LinearGradientBrush>
                                        </Border.BorderBrush>
                                        <Border.Background>
                                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                <GradientStop Color="#FF8AB4FF" Offset="1"/>
                                                <GradientStop Color="#FFD1E2FF" Offset="0"/>
                                            </LinearGradientBrush>
                                        </Border.Background>
                                    </Border>
                                </Grid>
                        </DockPanel>

                        <ControlTemplate.Triggers>
                            <Trigger Property="IsChecked" Value="True">
                                <Trigger.ExitActions>
                                    <BeginStoryboard Storyboard="{StaticResource OnUnchecking}" x:Name="OnUnchecking_BeginStoryboard"/>
                                </Trigger.ExitActions>
                                <Trigger.EnterActions>
                                    <BeginStoryboard Storyboard="{StaticResource OnChecking}" x:Name="OnChecking_BeginStoryboard"/>
                                </Trigger.EnterActions>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="False">
                                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

    <Grid x:Name="LayoutRoot">
        <CheckBox HorizontalAlignment="Center" Style="{DynamicResource CheckBoxStyle1}" VerticalAlignment="Center" Content="CheckBox"/>
    </Grid>
</Window>

如果您感兴趣,我还建议您阅读WPF中的样式和模板。

wvt8vs2t

wvt8vs2t2#

我根据arconaut的帖子用橙子和蓝色创建了一些样式。
截图:

我希望我的风格更接近iOS设备的开关风格。这种风格的一个区别是,滑动动画只滑动开关,而不是下面的指示器。也许如果我能找到一些时间,我会修改它的方式。在那之前,我想分享我的结果。它不完美,但这里是代码。

<LinearGradientBrush x:Key="CheckedBlue" StartPoint="0,0" EndPoint="0,1">
  <GradientStop Color="#FF285AB3" Offset="0" />
  <GradientStop Color="#FF4184EC" Offset="0.5" />
  <GradientStop Color="#FF558BED" Offset="0.5" />
  <GradientStop Color="#FF7DACF0" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="CheckedOrange" StartPoint="0,0" EndPoint="0,1">
  <GradientStop Color="#FFCA6A13" Offset="0" />
  <GradientStop Color="#FFF67D0C" Offset="0.2" />
  <GradientStop Color="#FFFE7F0C" Offset="0.2" />
  <GradientStop Color="#FFFA8E12" Offset="0.5" />
  <GradientStop Color="#FFFF981D" Offset="0.5" />
  <GradientStop Color="#FFFCBC5A" Offset="1" />
</LinearGradientBrush>
<SolidColorBrush x:Key="CheckedOrangeBorder" Color="#FF8E4A1B" />
<SolidColorBrush x:Key="CheckedBlueBorder" Color="#FF143874" />
<Style x:Key="OrangeSwitchStyle" TargetType="{x:Type CheckBox}">
  <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
  <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type CheckBox}">
        <ControlTemplate.Resources>
          <Storyboard x:Key="OnChecking">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
              <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="53" />
            </DoubleAnimationUsingKeyFrames>
          </Storyboard>
          <Storyboard x:Key="OnUnchecking">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
              <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0" />
            </DoubleAnimationUsingKeyFrames>
          </Storyboard>
        </ControlTemplate.Resources>
        <DockPanel x:Name="dockPanel">
          <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplate="{TemplateBinding ContentTemplate}" RecognizesAccessKey="True" VerticalAlignment="Center" />
          <Grid>
            <Border x:Name="BackgroundBorder" BorderBrush="#FF939393" BorderThickness="1" CornerRadius="3" Height="27" Width="94">
              <Border.Background>
                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                  <GradientStop Color="#FFB5B5B5" Offset="0" />
                  <GradientStop Color="#FFDEDEDE" Offset="0.1" />
                  <GradientStop Color="#FFEEEEEE" Offset="0.5" />
                  <GradientStop Color="#FFFAFAFA" Offset="0.5" />
                  <GradientStop Color="#FFFEFEFE" Offset="1" />
                </LinearGradientBrush>
              </Border.Background>
              <Grid>
                <Grid.ColumnDefinitions>
                  <ColumnDefinition /><ColumnDefinition />
                </Grid.ColumnDefinitions>
                <Ellipse x:Name="Off" Width="14" Height="14" Stroke="#FF7A7A7A" StrokeThickness="2" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
                <Line x:Name="On" X1="0" Y1="0" X2="0" Y2="14" Stroke="#FF7A7A7A" StrokeThickness="2" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" />
              </Grid>
            </Border>
            <Border BorderBrush="#FF939393" HorizontalAlignment="Left" x:Name="slider" Width="41" Height="27" BorderThickness="1" CornerRadius="3" RenderTransformOrigin="0.5,0.5" Margin="0">
              <Border.RenderTransform>
                <TransformGroup>
                  <ScaleTransform ScaleX="1" ScaleY="1" />
                  <SkewTransform AngleX="0" AngleY="0" />
                  <RotateTransform Angle="0" />
                  <TranslateTransform X="0" Y="0" />
                </TransformGroup>
              </Border.RenderTransform>
              <Border.Background>
                <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                  <GradientStop Color="#FFF0F0F0" Offset="0" />
                  <GradientStop Color="#FFCDCDCD" Offset="0.1" />
                  <GradientStop Color="#FFFBFBFB" Offset="1" />
                </LinearGradientBrush>
              </Border.Background>
            </Border>
          </Grid>
        </DockPanel>
        <ControlTemplate.Triggers>
          <Trigger Property="IsChecked" Value="True">
            <Trigger.ExitActions>
              <BeginStoryboard Storyboard="{StaticResource OnUnchecking}" x:Name="OnUnchecking_BeginStoryboard" />
            </Trigger.ExitActions>
            <Trigger.EnterActions>
              <BeginStoryboard Storyboard="{StaticResource OnChecking}" x:Name="OnChecking_BeginStoryboard" />
            </Trigger.EnterActions>
            <Setter TargetName="On" Property="Stroke" Value="White" />
            <Setter TargetName="Off" Property="Stroke" Value="White" />
            <!-- Change Orange or Blue color here -->
            <Setter TargetName="BackgroundBorder" Property="Background" Value="{StaticResource CheckedOrange}" />
            <Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="{StaticResource CheckedOrangeBorder}" />
          </Trigger>
          <Trigger Property="IsEnabled" Value="False">
            <!-- ToDo: Add Style for Isenabled == False -->
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
yhqotfr8

yhqotfr83#

一些开源ToggleSwitch:

nfs0ujit

nfs0ujit4#

我刚刚发布了一个关于这个的条目,它提供了一个适当的滑动动作,完全的可配置性,不需要是一个固定的大小(很恼火,因为我在网上找不到任何提供这样一个解决方案的东西)。
您可以在这里找到它:http://itsallaboutthexaml.blogspot.com/2012/01/variables-in-animation.html

cbwuti44

cbwuti445#

我也开始完成同样的任务,但是这些示例在产品代码中有一点欠缺。例如,如果您将文本(如On/Off或文本的本地化版本)放入控件中,答案是您必须定义控件的大小,因为在呈现控件之后,您无法修改动画或模板触发器。所有不适用于本地化文本解决方案。
我的解决方案是使用控件的Loaded事件和FrameworkElementFactory类动态创建控件的模板。我不得不说,这是非常复杂的,但可以实现。简单地说,在您的代码后面,创建一个模板,如所述,设置您的开/关文本的依赖属性,使用文本度量来确定控件的宽度,高度和动画值。
很抱歉,我不能发布解决方案,因为它现在属于Avanquest。
请在SystemSuite和Fix-It 12中查找。

q35jwt9p

q35jwt9p6#

我喜欢arconaut的不错的原型,我添加了一些代码来让边界变圆。
您必须从Grid声明中删除“Background”属性,并在Grid声明和第一个TextBlock声明之间添加以下行:

<Border
    x:Name="back"
    CornerRadius="3,3,3,3"
    BorderThickness="1"
    BorderBrush="#FFC0CCD9"
    >
    <Rectangle Fill="#FFC0CCD9"/>
</Border>

相关问题