WP7应用开发笔记 - IP输入框控件

虫虫 发布于 2012/02/21 17:26
阅读 563
收藏 2

因为需要在手机上配置IP,我需要一个界面输入IP地址,虽然直接使用TextBox,但是这样不太友好,我希望能够有和Windows网络设置上一样的IP输入框。所以决定写一个自定义控件。

设计控件外观

4个TextBox和3个显示“.”的TextBlock就可以了,结构很简单:

XAML代码如下:

<StackPanel Orientation="Horizontal" Height="72" >         
	<TextBox x:Name="TextOctet1"/>         
	<TextBlock Text="." />         
	<TextBox x:Name="TextOctet2"/>         
	<TextBlock Text="." />         
	<TextBox x:Name="TextOctet3"/>         
	<TextBlock Text="." />         
	<TextBox x:Name="TextOctet4"/>     
</StackPanel>

因为IP地址里面只有数字和“.”,而且每位地址最长为3。为了限制输入将样式设置如下:

<UserControl.Resources>         
	<Style TargetType="TextBox">             
		<Setter Property="Width" Value="90"/>             
		<Setter Property="MaxLength" Value="3"/>             
		<Setter Property="TextAlignment" Value="Right"/>            
		<Setter Property="InputScope" Value="Number"/>         
	</Style>         
	<Style TargetType="TextBlock">             
		<Setter Property="Margin" Value="5,30,5,0"/>         
	</Style>     
</UserControl.Resources>

 InputScope设置为Number,限制输入数字和.。

InputScope

复习一下WP里面有一个叫做InputScope的依赖属性,这个是软输入面板设置 在WP里面非常有用的属性。支持的名称和功能如下:

受 Silverlight for Windows Phone 支持
AddressCity 城市地址的文本输入模式。

受 Silverlight for Windows Phone 支持
AddressCountryName 国家/地区的名称的文本输入模式。

受 Silverlight for Windows Phone 支持
AddressCountryShortName 国家/地区的缩写名称的文本输入模式。

受 Silverlight for Windows Phone 支持
AddressStateOrProvince 省/市/自治区的文本输入模式。

受 Silverlight for Windows Phone 支持
AddressStreet 街道地址的文本输入模式。

受 Silverlight for Windows Phone 支持
AlphanumericFullWidth 字母数字全角字符的文本输入模式。

受 Silverlight for Windows Phone 支持
AlphanumericHalfWidth 字母数字半角字符的文本输入模式。

受 Silverlight for Windows Phone 支持
ApplicationEnd 不支持。仅限在 用于 Windows Phone 的 Silverlight 中内部使用。

受 Silverlight for Windows Phone 支持
Bopomofo 汉语拼音语音转换系统的文本输入模式。

受 Silverlight for Windows Phone 支持
Chat 用于文本消息传递的 SIP 布局,可识别预定义的缩写。仅在 用于 Windows Phone 的 Silverlight 中受支持。

受 Silverlight for Windows Phone 支持
CurrencyAmount 货币数量的文本输入模式。

受 Silverlight for Windows Phone 支持
CurrencyAmountAndSymbol 货币数量和符号的文本输入模式。

受 Silverlight for Windows Phone 支持
CurrencyChinese 中国货币的文本输入模式。

受 Silverlight for Windows Phone 支持
Date 日历日期的文本输入模式。

受 Silverlight for Windows Phone 支持
DateDay 日历日期中数字日期的文本输入模式。

受 Silverlight for Windows Phone 支持
DateDayName 日历日期中日期名称的文本输入模式。

受 Silverlight for Windows Phone 支持
DateMonth 日历日期中数字月份的文本输入模式。

受 Silverlight for Windows Phone 支持
DateMonthName 日历日期中月份名称的文本输入模式。

受 Silverlight for Windows Phone 支持
DateYear 日历日期中年份的文本输入模式。

受 Silverlight for Windows Phone 支持
Default 输入命令的默认处理。

受 Silverlight for Windows Phone 支持
Digits 数字的文本输入模式。

受 Silverlight for Windows Phone 支持
EmailNameOrAddress 用于电子邮件名称或地址的 SIP 布局。仅在 用于 Windows Phone 的 Silverlight 中受支持。

受 Silverlight for Windows Phone 支持
EmailSmtpAddress 简单邮件传输协议 (SMTP) 电子邮件地址的文本输入模式。

受 Silverlight for Windows Phone 支持
EmailUserName 电子邮件用户名的文本输入模式。

受 Silverlight for Windows Phone 支持
EnumString 不支持。仅限在 用于 Windows Phone 的 Silverlight 中内部使用。

受 Silverlight for Windows Phone 支持
FileName  文件名的文本输入模式。

受 Silverlight for Windows Phone 支持
FullFilePath 文件完整路径的文本输入模式。

受 Silverlight for Windows Phone 支持
Hanja 朝鲜文汉字字符的文本输入模式。

受 Silverlight for Windows Phone 支持
Hiragana 平假名书写体系的文本输入模式。

受 Silverlight for Windows Phone 支持
KatakanaFullWidth 全角片假名字符的文本输入模式。

受 Silverlight for Windows Phone 支持
KatakanaHalfWidth 半角片假名字符的文本输入模式。

受 Silverlight for Windows Phone 支持
LogOnName 登录名的文本输入模式。

受 Silverlight for Windows Phone 支持
Maps 用于输入地图位置的 SIP 布局。仅在 用于 Windows Phone 的 Silverlight 中受支持。

受 Silverlight for Windows Phone 支持
NameOrPhoneNumber 用于 SMS“至”字段的 SIP 布局。仅在 用于 Windows Phone 的 Silverlight 中受支持。

受 Silverlight for Windows Phone 支持
Number 数字的文本输入模式。

受 Silverlight for Windows Phone 支持
NumberFullWidth 全角数字的文本输入模式。

受 Silverlight for Windows Phone 支持
OneChar 某个字符的文本输入模式。

受 Silverlight for Windows Phone 支持
Password 密码的文本输入模式。

受 Silverlight for Windows Phone 支持
PersonalFullName 个人的全名的文本输入模式。

受 Silverlight for Windows Phone 支持
PersonalGivenName 个人的名字的文本输入模式。

受 Silverlight for Windows Phone 支持
PersonalMiddleName 个人的中间名的文本输入模式。

受 Silverlight for Windows Phone 支持
PersonalNamePrefix 个人姓名前缀的文本输入模式。

受 Silverlight for Windows Phone 支持
PersonalNameSuffix 个人姓名后缀的文本输入模式。

受 Silverlight for Windows Phone 支持
PersonalSurname 个人的姓的文本输入模式。

受 Silverlight for Windows Phone 支持
PhraseList 词组列表的文本输入模式。

受 Silverlight for Windows Phone 支持
PostalAddress 邮寄地址的文本输入模式。

受 Silverlight for Windows Phone 支持
PostalCode 邮政编码的文本输入模式。

受 Silverlight for Windows Phone 支持
Private 不支持。仅限在 用于 Windows Phone 的 Silverlight 中的内部使用。

受 Silverlight for Windows Phone 支持
RegularExpression 正则表达式的文本输入模式。

受 Silverlight for Windows Phone 支持
Search 用于搜索查询的 SIP 布局。仅在 用于 Windows Phone 的 Silverlight 中受支持。

受 Silverlight for Windows Phone 支持
Srgs 语音识别语法规范 (SRGS) 的文本输入模式。

受 Silverlight for Windows Phone 支持
TelephoneAreaCode 区号的文本输入模式。

受 Silverlight for Windows Phone 支持
TelephoneCountryCode 电话的国家/地区代码的文本输入模式。

受 Silverlight for Windows Phone 支持
TelephoneLocalNumber 本地电话号码的文本输入模式。

受 Silverlight for Windows Phone 支持
TelephoneNumber 电话号码的文本输入模式。

受 Silverlight for Windows Phone 支持
Text 用于标准文本输入的软件输入面板 (SIP) 布局。仅在 用于 Windows Phone 的 Silverlight 中受支持。

受 Silverlight for Windows Phone 支持
Time 时间的文本输入模式。

受 Silverlight for Windows Phone 支持
TimeHour 小时的文本输入模式。

受 Silverlight for Windows Phone 支持
TimeMinorSec 时间的分钟或秒的文本输入模式。

受 Silverlight for Windows Phone 支持
Url 统一资源定位符 (URL) 的文本输入模式。

受 Silverlight for Windows Phone 支持
Xml XML 的文本输入模式。

受 Silverlight for Windows Phone 支持
Yomi 不支持。仅限在 用于 Windows Phone 的 Silverlight 中内部使用。

控件代码实现

先定义一下叫IPAddress的依赖属性,复习一下:

public static readonly DependencyProperty IPAddressProperty = DependencyProperty.Register(
	"IPAddress", 
	typeof(string), 
	typeof(IPBox), 
	new PropertyMetadata(String.Empty, IPPropertyChangedCallback)
);        

private static void IPPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs arg){
	var value = (string)arg.NewValue;            
	if (string.IsNullOrWhiteSpace(value)) 
		return;            
	var ipBox = (IPBox)sender;            
	ipBox.SetIPAddress(value);        
}        

[Description("获取或设置IP")]        
[Category("Common Properties")]        
public string IPAddress {            
	get { return (string)GetValue(IPAddressProperty); }            
	set { SetValue(IPAddressProperty, value); }        
}

需要实现的功能有

  • 限制输入范围为0~255
  • 输入“.”自动将焦点跳到下一个TextBox
  • 输入到3个数字的时候,自动将焦点跳到下一个TextBox
  • 按Back键如果当前TextBox没有文本,需要自动将焦点跳到前一个TextBox

 

实现这些功能需要对每个TextBox监听TextChanged和KeyDown事件,并作相应处理。

完整代码如下:

public partial class IPBox
    {
        public static readonly DependencyProperty IPAddressProperty =
            DependencyProperty.Register("IPAddress", typeof(string), typeof(IPBox),
            new PropertyMetadata(String.Empty, IPPropertyChangedCallback));

        private static void IPPropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs arg)
        {
            var value = http://www.cnblogs.com/kiminozo/archive/2012/01/26/(string)arg.NewValue;
            if (string.IsNullOrWhiteSpace(value)) return;
            var ipBox = (IPBox)sender;
            ipBox.SetIPAddress(value);
        }

        [Description("获取或设置IP")]
        [Category("Common Properties")]
        public string IPAddress
        {
            get { return (string)GetValue(IPAddressProperty); }
            set { SetValue(IPAddressProperty, value); }
        }

        private readonly TextBox[] textBoxs;
        private readonly string[] ipParts;

        public IPBox()
        {
            InitializeComponent();

            textBoxs = new[]
                           {
                               TextOctet1,
                               TextOctet2,
                               TextOctet3,
                               TextOctet4
                           };
            ipParts = new string[4];
            for (int i = ; i < 4; i++)
            {
                var box = textBoxs[i];
                box.Tag = i;
                box.TextChanged += OnTextChanged;
                box.KeyDown += OnKeyDown;
            }
        }

        private void UpdateIPAddress()
        {
            for (int i = ; i < 4; i++)
            {
                ipParts[i] = textBoxs[i].Text;
            }
            if (ipParts.Any(string.IsNullOrWhiteSpace)) return;
            IPAddress = string.Format("{0}.{1}.{2}.{3}", TextOctet1.Text, TextOctet2.Text, TextOctet3.Text,
                                      TextOctet4.Text);
        }

        private void SetIPAddress(string value)
        {
            IPAddress tmp;
            if (!System.Net.IPAddress.TryParse(value, out tmp)) return;

            string[] octets = value.Split('.');
            for (int i = ; i < 4; i++)
            {
                if (ipParts[i] != octets[i])
                {
                    ipParts[i] = octets[i];
                    textBoxs[i].Text = octets[i];
                }
            }


        }

        private void OnTextChanged(object sender, TextChangedEventArgs e)
        {
            var textBox = (TextBox)sender;
            var index = (int)textBox.Tag;

            if (string.IsNullOrWhiteSpace(textBox.Text)) return;
            if (int.Parse(textBox.Text) > 255)
            {
                textBox.Text = "255";
                textBox.Select(3, );
            }

            if (ipParts[index] == textBox.Text) return;
            if (textBox.Text.Length == 3)
            {
                NextFocus(index);
            }
            UpdateIPAddress();
        }

        private void OnKeyDown(object sender, KeyEventArgs e)
        {
            var textBox = (TextBox)sender;
            if (e.PlatformKeyCode == 190) //.             {
                e.Handled = true;
                if (!string.IsNullOrEmpty(textBox.Text))
                {
                    NextFocus((int)textBox.Tag);
                }
                return;
            }
            if (e.Key == Key.Back)
            {
                if (string.IsNullOrEmpty(textBox.Text))
                {
                    e.Handled = true;
                    PrevFocus((int)textBox.Tag);
                }
            }
        }

        private void NextFocus(int index)
        {
            if (index >= 3) return;
            var box = textBoxs[index + 1];
            box.Focus();
            box.Select(box.Text.Length, );
        }

        private void PrevFocus(int index)
        {
            if (index < 1) return;
            var box = textBoxs[index - 1];
            box.Focus();
            box.Select(box.Text.Length, );
        }
    }

加载中
返回顶部
顶部