zoukankan      html  css  js  c++  java
  • 用Silverlight打造位运算器(2)--制作数字文本框控件

    上一篇文章中,我们介绍了如何制作一个简易工具条,要完成位运算器,还需要一个很重要的控件,就是放数字的编辑框。在我的构想中这个编辑框所拥有以下功能:
    1、 不允许输入非法字符,如十进制时只能输入数字0-9和负号。
    2、 可以很方便地在各个进制间进行转换。
          关于第1点,最完美的解决方案就是在KeyDown事件中过滤字符,然后使用e.Handle=true方法来通知编辑框不再处理这次键盘按下事件,它最大的优点在于光标位置不会改变,但这个方法无法解决字符串粘贴时所带的非法字符。本来我想在TextChanged事件中做同样的处理,结果发现TextChanged事件中没有e.Handle参数,一查帮助,发现这个事件是异步事件,无法终止。上网找,中文资料,英文资料都找了,没找到合适的解决方案。最后没办法,只好自己在TextChanged事件里解决了。判断非法字符使用了正则表达式,以前不知道正则表达式,这里写得很痛苦,现在安逸多了。但总体来说,解决得并不是很完美,发生异常时光标无法定位在原来的位置,应该可以在SelectionChanged事件里解决这个问题,不过并未尝试,期待哪位大侠能给出完美的解决方案。
          写这个控件时遇到的第二个问题是如果在控件的TextChanged事件里抛出异常,我居然不知道在哪里可以捕捉这些异常,有点诡异,还是期待有人能给出答案。没办法,如果不处理这些异常,用户在狂按键盘都无法输入字符时可能会认为我的程序挂掉了。只好另辟蹊径,在编辑框控件上方安装一个简易的弹出式消息框,这样做不是很规范,但先把问题解决了再说。这里还有一个问题未解决,就是如何计算一个字符串所占用的像素长度,学习有时就是这么痛苦!
          这个控件完成后,我又发现了一个非常严重的问题:工具条在载入浏览器后无法使其中一个按钮处于按下状态,我的猜测是SpeedButton使用模板显示其外观,在载入窗体进行绘制时,必须按照默认状态进行绘制,对此我束手无策,还是希望有高手能给出答案。现在我能想出的解决办法就是不使用模板来显示外观,重写SpeedButton,这个留到下篇文章一起完成吧。
    好,先来看看效果,这里需要注意,必须安装Silverlight 3.0版本才能正常运行示例。

    请注意,工具条的BCD按钮本应该是处于按下状态的。
    制作步骤:
    1、在【BitLibrary】项目上单击鼠标右键,选择【添加】【新建项】,添加一个Silverlight用户控件,并命名为“BitTextBox.xaml”。更改BitTextBox.xaml文件如下:

    <UserControl x:Class="BitLibrary.BitTextBox"
        xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml">
        
    <Canvas x:Name="LayoutRoot" Height="47" Width="335">
            
    <TextBox x:Name="BitTxt" Text="0" FontSize="16" TextAlignment="Right" 
                     Canvas.Left
    ="0" Canvas.Top="17" Height="30" Width="335" AcceptsReturn="False"/>
            
    <Border x:Name="TipBorder" Canvas.Top="0" Canvas.Left="60" Height="18" Width="275" BorderBrush="Red"
                    BorderThickness
    ="2" Background="#00ffffff" Visibility="Collapsed">
                
    <Border.Resources>
                    
    <Storyboard x:Name="Story" Completed="Story_Completed">
                        
    <ColorAnimationUsingKeyFrames Storyboard.TargetName="TipBorder"                                                  Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)">
                            
    <DiscreteColorKeyFrame Value="#FF718597" KeyTime="00:00:0.5" />
                            
    <DiscreteColorKeyFrame Value="Red" KeyTime="00:00:1" />
                            
    <DiscreteColorKeyFrame Value="#FF718597" KeyTime="00:00:1.5" />
                            
    <DiscreteColorKeyFrame Value="Red" KeyTime="00:00:2" />
                        
    </ColorAnimationUsingKeyFrames>
                        
    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="TipBorder"
                                         Storyboard.TargetProperty
    ="Opacity">
                            
    <DiscreteDoubleKeyFrame Value="1" KeyTime="0:0:3"/>
                            
    <LinearDoubleKeyFrame Value="0" KeyTime="0:0:4" />
                        
    </DoubleAnimationUsingKeyFrames>
                    
    </Storyboard>
                
    </Border.Resources>
                
    <TextBlock x:Name="TxtMsg" TextAlignment="Right"/>
            
    </Border>
        
    </Canvas>
    </UserControl>

         这里在Canvas上方是一个Border内含TextBlock,TextBlock用于显示异常信息,Border显示动画,也就是闪两下,然后消失。Canvas下方是编辑框控件,用于显示二到十六进制的数字。
    2、打开BitTextBox.xaml.cs文件,更改代码如下:

      1 public partial class BitTextBox : UserControl
      2     {
      3         //二进制到十六进制的正则表达式
      4         const string BIN_EXPRESSION = "^[0-1]*$";
      5         const string OCT_EXPRESSION = "^[0-7]*$";
      6         const string BCD_EXPRESSION = "^[0-9-][0-9]*$";
      7         const string HEX_EXPRESSION = "^[a-f0-9A-F]*$";
      8         public BitTextBox()
      9         {
     10             InitializeComponent();
     11             BitTxt.TextChanged += new TextChangedEventHandler(BitTxt_TextChanged);
     12         }
     13         //声明依赖属性Text
     14         public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
     15             "Text"typeof(string), typeof(BitTextBox), null);
     16         public string Text
     17         {
     18             get { return BitTxt.Text; }
     19             set { Value = Convert.ToInt32(value, (int)state); }
     20         }
     21 
     22         string CurrentRegular = BCD_EXPRESSION;//记录当前所使用的正则表达式
     23         int value;
     24         public int Value//编辑框内所表示的整数值
     25         {
     26             get { return this.value; }
     27             set
     28             {
     29                 this.value = value;
     30                 SetTextFromValue();
     31             }
     32         }
     33         bool fillZero = true;
     34         public bool FillZero //指示,当显示为二进制时,高位不足处是否填充0
     35         {
     36             get { return fillZero; }
     37             set
     38             {
     39                 fillZero = value;
     40                 if (state == SystemState.Bin)
     41                 {
     42                     SetTextFromValue();
     43                 }
     44             }
     45         }
     46         SystemState state = SystemState.Bcd;//编辑框的当前进制状态
     47         public SystemState State
     48         {
     49             get { return state; }
     50             set
     51             {
     52                 if (state == value) return;
     53                 switch (value)
     54                 {
     55                     case SystemState.Bin:
     56                         CurrentRegular = BIN_EXPRESSION;
     57                         break;
     58                     case SystemState.Oct:
     59                         CurrentRegular = OCT_EXPRESSION;
     60                         break;
     61                     case SystemState.Bcd:
     62                         CurrentRegular = BCD_EXPRESSION;
     63                         break;
     64                     case SystemState.Hex:
     65                         CurrentRegular = HEX_EXPRESSION;
     66                         break;
     67                 }
     68                 //转换进制
     69                 state = value;
     70                 SetTextFromValue();
     71             }
     72         }
     73         //显示错误提示
     74         public void ShowTip(string msg) 
     75         {
     76             TxtMsg.Text = msg;
     77             TipBorder.Visibility = Visibility.Visible;
     78             TipBorder.Opacity = 1;
     79             Story.Begin();
     80         }
     81         private void Story_Completed(object sender, EventArgs e)
     82         {
     83             TipBorder.Visibility = Visibility.Collapsed;
     84         }
     85         //清空编辑框内的数字
     86         public void Clear()
     87         {
     88             Value = 0;
     89             BitTxt.Focus();
     90             BitTxt.SelectionStart = 0;
     91             BitTxt.SelectionLength = 1;
     92         }
     93         void BitTxt_TextChanged(object sender, TextChangedEventArgs e)
     94         {
     95             string str = BitTxt.Text;
     96             if (str == "-" && state==SystemState.Bcd)
     97             {
     98                 return;
     99             }
    100             //正则表达式验证
    101             if (!Regex.IsMatch(str, CurrentRegular))
    102             {
    103                 SetTextFromValue();
    104                 switch (state) //显示异常信息
    105                 {
    106                     case SystemState.Bin:
    107                         ShowTip("只能输入数字“0”和“1”");
    108                         break;
    109                     case SystemState.Oct:
    110                         ShowTip("只能输入0~7之间的数字");
    111                         break;
    112                     case SystemState.Bcd:
    113                         ShowTip("只能输入0~9之间的数字");
    114                         break;
    115                     case SystemState.Hex:
    116                         ShowTip("只能输入数字0~9和字母a~f");
    117                         break;
    118                 }
    119                 return;
    120             }
    121             //出现空白时
    122             if (str == "")
    123             {
    124                 value = 0;
    125                 BitTxt.Text = "0";
    126                 return;
    127             }
    128             //防止数字超出int32所能容纳的范围
    129             try
    130             {
    131                 int i = Convert.ToInt32(str, (int)state);
    132             }
    133             catch
    134             {
    135                 SetTextFromValue();
    136                 ShowTip("您所输入的数字超出了32位有符号整数所能承受的范围");
    137                 return;
    138             }
    139             value = Convert.ToInt32(str, (int)state);
    140             BitTxt.Text = str.ToUpper();
    141         }
    142         //将值变成相应进制的字符串并赋给文本框
    143         void SetTextFromValue()
    144         {
    145             string temp = Convert.ToString(this.value, (int)state).ToUpper();
    146             if (state == SystemState.Bin && fillZero)
    147             {
    148                 temp = temp.PadLeft(32'0');
    149             }
    150             BitTxt.Text = temp;
    151         }
    152 }

    这里声明了一个依赖属性Text,因为需要在Xaml文件中直接给编辑框赋文本值。如果你想在Xaml文件中调用其他文件,也可以声明它的依赖属性。
    3、 更改MainPage.xaml代码如下:

    <UserControl x:Class="BitCalculator.MainPage"
        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:src
    ="clr-namespace:BitLibrary;assembly=BitLibrary"
        mc:Ignorable
    ="d" d:DesignWidth="470" d:DesignHeight="70">
        
    <Canvas x:Name="LayoutRoot" Background="Goldenrod">
            
    <src:ToolBar x:Name="toolBar" Grid.Row="1" SelectionChange="toolBar_SelectionChange"
                         Canvas.Left
    ="10" Canvas.Top="17"/>
            
    <src:BitTextBox x:Name="txtBox" Text="20091122" Canvas.Left="132" Canvas.Top="0"/> 
            
    <CheckBox x:Name="cbFillZero" Content="二进制数字不足32位补0" IsChecked="true"
                      Canvas.Left
    ="132" Canvas.Top="52" Click="cbFillZero_Click"/>
        
    </Canvas>
    </UserControl>

     4、 打开MainPage.xaml.cs,更改代码如下:

     1 public partial class MainPage : UserControl
     2 {
     3         public MainPage()
     4         {
     5             InitializeComponent();
     6         }
     7 
     8         private void toolBar_SelectionChange(object sender, RoutedEventArgs e)
     9         {
    10             txtBox.State = toolBar.ToolState;
    11         }
    12 
    13         private void cbFillZero_Click(object sender, RoutedEventArgs e)
    14         {
    15             if (txtBox != null)
    16             {
    17                 txtBox.FillZero = !txtBox.FillZero;
    18             }
    19         }
    20 }

    现在一个位运算器的雏形已经完成,可以在这个程序里进行进制转换。虽然现在还带着很多的疑惑,但学习的乐趣就在于此,发现问题,解决问题,获取知识和经验。


     

  • 相关阅读:
    mybatis
    eclipse日志
    最大值与最小值问题
    常见的缓存算法设计策略
    常用垃圾回收算法
    Java中对象的三种状态
    Java中的内存泄漏问题
    单例模式
    约瑟夫环问题
    矩形覆盖问题
  • 原文地址:https://www.cnblogs.com/abatei/p/1608446.html
Copyright © 2011-2022 走看看