WP7应用开发笔记(8) IP输入框控件

因为需要在手机上配置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事件,并作相应处理。

完整代码如下:

View Code
    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 = (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 = 0; i < 4; i++)
{
var box = textBoxs[i];
box.Tag = i;
box.TextChanged += OnTextChanged;
box.KeyDown += OnKeyDown;
}
}

private void UpdateIPAddress()
{
for (int i = 0; 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 = 0; 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, 0);
}

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, 0);
}

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


 

posted @ 2012-01-26 12:08  kiminozo  阅读(1478)  评论(0编辑  收藏  举报