今天大清早起床打开微信朋友圈看到大学同学院一哥们发的结婚的照片,在此遥祝一对新人:新婚快乐,百年好合!这哥们大学时时班长,结婚也来了好多同学,不由得觉得吾等屌丝大学确实留下了很多遗憾~哦,对了,这哥们还跟我现在在一个公司的不同部门里,听说他也混的如鱼得水,祝福!
转到正题,今天想记录的知识点有三个:
1.wpf样式实现安卓和苹果移动终端上的 滑块式开关 ;
2. wpf转换器 的使用;
说说需求,项目上要手动打开配置文件修改里面的值,确切来说是在true和false中间切换里面一个配置的值。想着给客户上线使用,让他们打开配置文件切换值肯定是不好的,就想着做个图形界面的开关。觉得手机终端的滑块式开关不错,就自己写了一个。先看手机上的滑块式开关是什么样的:
对,就要这种效果。
先看XAML界面的代码吧:
1 <Window x:Class="ModifyConfig.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:local="clr-namespace:ModifyConfig" 5 Title="MainWindow" 6 Width="525" 7 Height="350"> 8 <Window.Resources> 9 10 <local:GradeState x:Key="GradeState" /> 11 12 <Style x:Key="CheckRadioFocusVisual"> 13 <Setter Property="Control.Template"> 14 <Setter.Value> 15 <ControlTemplate> 16 <Rectangle Margin="14,0,0,0" 17 SnapsToDevicePixels="true" 18 Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" 19 StrokeDashArray="1 2" 20 StrokeThickness="1" /> 21 </ControlTemplate> 22 </Setter.Value> 23 </Setter> 24 </Style> 25 <Style x:Key="SliderCheckBox" TargetType="{x:Type CheckBox}"> 26 <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" /> 27 <Setter Property="BorderThickness" Value="1" /> 28 <Setter Property="Cursor" Value="Hand" /> 29 <Setter Property="Template"> 30 <Setter.Value> 31 <ControlTemplate TargetType="{x:Type CheckBox}"> 32 <ControlTemplate.Resources> 33 <Storyboard x:Key="StoryboardIsChecked"> 34 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="CheckFlag" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"> 35 <EasingDoubleKeyFrame KeyTime="0" Value="0" /> 36 <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="14" /> 37 </DoubleAnimationUsingKeyFrames> 38 </Storyboard> 39 <Storyboard x:Key="StoryboardIsCheckedOff"> 40 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="CheckFlag" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"> 41 <EasingDoubleKeyFrame KeyTime="0" Value="14" /> 42 <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0" /> 43 </DoubleAnimationUsingKeyFrames> 44 </Storyboard> 45 </ControlTemplate.Resources> 46 <BulletDecorator Background="Transparent" SnapsToDevicePixels="true"> 47 <BulletDecorator.Bullet> 48 <Border x:Name="ForegroundPanel" 49 Width="35" 50 Height="20" 51 BorderThickness="1" 52 CornerRadius="10"> 53 <Canvas> 54 <Border x:Name="CheckFlag" 55 Width="19" 56 Height="18" 57 VerticalAlignment="Center" 58 Background="{Binding Converter={StaticResource GradeState} }" 59 BorderThickness="1" 60 CornerRadius="10" 61 RenderTransformOrigin="0.5,0.5"> 62 <Border.RenderTransform> 63 <TransformGroup> 64 <ScaleTransform /> 65 <SkewTransform /> 66 <RotateTransform /> 67 <TranslateTransform /> 68 </TransformGroup> 69 </Border.RenderTransform> 70 <Border.Effect> 71 <DropShadowEffect Direction="180" ShadowDepth="1" /> 72 </Border.Effect> 73 </Border> 74 </Canvas> 75 </Border> 76 </BulletDecorator.Bullet> 77 <ContentPresenter Margin="{TemplateBinding Padding}" 78 HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 79 VerticalAlignment="Center" 80 RecognizesAccessKey="True" 81 SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> 82 </BulletDecorator> 83 <ControlTemplate.Triggers> 84 <Trigger Property="HasContent" Value="true"> 85 <Setter Property="FocusVisualStyle" Value="{StaticResource CheckRadioFocusVisual}" /> 86 <Setter Property="Padding" Value="4,0,0,0" /> 87 </Trigger> 88 <Trigger Property="IsEnabled" Value="false"> 89 <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" /> 90 </Trigger> 91 <Trigger Property="IsChecked" Value="True"> 92 <Setter TargetName="ForegroundPanel" Property="Background" Value="LightGreen" /> 93 <Trigger.EnterActions> 94 <BeginStoryboard x:Name="BeginStoryboardCheckedTrue" Storyboard="{StaticResource StoryboardIsChecked}" /> 95 <RemoveStoryboard BeginStoryboardName="BeginStoryboardCheckedFalse" /> 96 </Trigger.EnterActions> 97 </Trigger> 98 <Trigger Property="IsChecked" Value="False"> 99 <Setter TargetName="ForegroundPanel" Property="Background" Value="LightGray" /> 100 <Trigger.EnterActions> 101 <BeginStoryboard x:Name="BeginStoryboardCheckedFalse" Storyboard="{StaticResource StoryboardIsCheckedOff}" /> 102 <RemoveStoryboard BeginStoryboardName="BeginStoryboardCheckedTrue" /> 103 </Trigger.EnterActions> 104 </Trigger> 105 </ControlTemplate.Triggers> 106 </ControlTemplate> 107 </Setter.Value> 108 </Setter> 109 </Style> 110 </Window.Resources> 111 <Canvas> 112 <TextBlock Text="是否开启考试模式:" Canvas.Left="27" Canvas.Top="12" /> 113 <CheckBox Width="200" 114 Height="23" 115 Style="{DynamicResource SliderCheckBox}" 116 x:Name="Switch_IsExamMode" 117 Click="IsExamMode_Click" Canvas.Left="132" Canvas.Top="12" /> 118 119 </Canvas> 120 </Window>
下面的是后台cs文件的代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Data; 8 using System.Windows.Documents; 9 using System.Windows.Input; 10 using System.Windows.Media; 11 using System.Windows.Media.Imaging; 12 using System.Windows.Navigation; 13 using System.Windows.Shapes; 14 using System.Xml; 15 using System.Globalization; 16 17 namespace ModifyConfig 18 { 19 /// <summary> 20 /// MainWindow.xaml 的交互逻辑 21 /// </summary> 22 public partial class MainWindow : Window 23 { 24 /// <summary> 25 /// 是否考试模式 26 /// </summary> 27 private bool _isExamMode; 28 29 /// <summary> 30 /// 是否考试模式 31 /// </summary> 32 public bool IsExamMode 33 { 34 get { return _isExamMode; } 35 set { _isExamMode = value; } 36 } 37 38 /// <summary> 39 /// 主窗口初始化 40 /// </summary> 41 public MainWindow() 42 { 43 InitializeComponent(); 44 Switch_IsExamMode.IsChecked = GetIsExamMode(); 45 IsExamMode = (bool)Switch_IsExamMode.IsChecked; 46 Switch_IsExamMode.DataContext = IsExamMode; 47 } 48 /// <summary> 49 /// 点击开关触发的事件 50 /// </summary> 51 /// <param name="sender"></param> 52 /// <param name="e"></param> 53 private void IsExamMode_Click(object sender, RoutedEventArgs e) 54 { 55 IsExamMode = (bool)Switch_IsExamMode.IsChecked; 56 Switch_IsExamMode.DataContext = IsExamMode; 57 SetIsExamMode(); 58 } 59 /// <summary> 60 /// 得到XML文件中的节点值 61 /// </summary> 62 /// <returns></returns> 63 private bool GetIsExamMode() 64 { 65 XmlDocument xmlDoc = new XmlDocument(); 66 xmlDoc.Load(@"../../../config/Platform.System.Config"); 67 XmlNodeList accountList = xmlDoc.SelectSingleNode("configuration").ChildNodes; 68 foreach (XmlNode account in accountList) 69 { 70 if (account.Name == "add" && account.Attributes["key"].Value.ToString() == "InExamMode") 71 { 72 return account.Attributes["value"].Value == "True" ? true : false; 73 } 74 } 75 return false; 76 } 77 /// <summary> 78 /// 向xml文件中写入值 79 /// </summary> 80 private void SetIsExamMode() 81 { 82 XmlDocument xmlDoc = new XmlDocument(); 83 xmlDoc.Load(@"../../../config/Platform.System.Config"); 84 XmlNodeList accountList = xmlDoc.SelectSingleNode("configuration").ChildNodes; 85 foreach (XmlNode account in accountList) 86 { 87 if (account.Name == "add") 88 { 89 //if account exists 90 if ("InExamMode" == account.Attributes["key"].Value.ToString()) 91 { 92 if ((bool)Switch_IsExamMode.IsChecked) 93 { 94 account.Attributes["value"].Value = "True"; 95 } 96 else 97 { 98 account.Attributes["value"].Value = "False"; 99 } 100 xmlDoc.Save(@"../../../config/Platform.System.Config"); 101 } 102 } 103 } 104 } 105 } 106 /// <summary> 107 /// 转换器 108 /// </summary> 109 public class GradeState : IValueConverter 110 { 111 public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 112 { 113 if (value == null) 114 return null; 115 dynamic data = value; 116 if ((bool)data) 117 return new SolidColorBrush(Colors.Green); 118 else 119 return new SolidColorBrush(Colors.Gray); 120 } 121 public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 122 { 123 throw new NotImplementedException(); 124 } 125 } 126 }
样式实现滑块开关没什么难度,说说转换器,转换器的使用,1.增加一个转换器的类,它继承于接口IValueConverter,2.实现该接口的两个方法,Convert(object value, Type targetType, object parameter, CultureInfo culture)和ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);第二个方法一般都是throw new NotImplementedException();3.XAML界面资源里声明该转换器(第10行);4.XAML界面需要转换的地方使用该转换器(第58行)。
xml文件的操作我这边比较简单,有读取节点属性值和设置节点值两个功能。
下面是我们的配置文件Platform.System.Config
1 <?xml version="1.0" encoding="utf-8"?> 2 <configuration> 3 <add key="TradeMainVersion" value="1" /> 4 <add key="IsDebugMode" value="False" /> 5 <add key="IsStartHardDiskNumber" value="False" /> 6 <add key="PlatformTitle" value="综合业务前端系统" /> 7 <add key="PagesDirectory" value="TellerSysPages" /> 8 <add key="UpdateApplication" value="TellerSystem.Update.exe" /> 9 <add key="TempFilePath" value="tmp/" /> 10 <add key="ConfigFilePath" value="TellerSysconf/" /> 11 <!--是否启动动画--> 12 <add key="AnimationEnable" value="True" /> 13 <!--是否启用权限控制--> 14 <add key="IsPowerCheckByUser" value="False" /> 15 <!--启用项目层更新交易dll True:项目层更新,False:底层更新 --> 16 <add key="IsFromProjectDownLoadTradeDll" value="False" /> 17 <!--是否启用客户端更新--> 18 <add key="IsUpdateCheckForClient" value="True" /> 19 <!--是否越过支付密码器检查--> 20 <add key="IsSkipCheckPayPassword" value="True" /> 21 <!--是否越过验印流水检查--> 22 <add key="IsSkipCheckYanYinWater" value="True" /> 23 <!--是否启用考试模式--> 24 <add key="InExamMode" value="False" /> 25 <!--是否外设调试模式--> 26 <add key="InDeviceDebugMode" value="True" /> 27 </configuration>
看看最后的运行结果:
关闭时:
开启时:
下载源码压缩包链接:http://files.cnblogs.com/files/zhangyongheng/ModifyConfig.rar
2015-05-05 10:43:53