wpf 自定义输入ip地址的文本框
xmal
PS:因为是上位机,所以文本框里面写了键盘,如果不需要可删除。
<UserControl x:Class="项目.IPTextBox"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:i="http://schemas.microsoft.com/xaml/behaviors"xmlns:keyboard="clr-namespace:Hs.KeyBoard.WPF.Behavior;assembly=Hs.KeyBoard.WPF"mc:Ignorable="d" Height="56" d:DesignWidth="800" FontSize="28"><Border Name="Border" CornerRadius="6" BorderBrush="White" BorderThickness="3" RenderOptions.EdgeMode="Aliased" Height="56" Background="#ECF3F9"Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Path=Width}" HorizontalAlignment="Left"><Grid Name="GridIPAddress" VerticalAlignment="Center"><Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="15"/><ColumnDefinition Width="*"/><ColumnDefinition Width="15"/><ColumnDefinition Width="*"/><ColumnDefinition Width="15"/><ColumnDefinition Width="*"/></Grid.ColumnDefinitions><TextBox Name="TbxIP1" HorizontalContentAlignment="Center" Background="Transparent" VerticalAlignment="Center"InputMethod.IsInputMethodEnabled="False" MaxLength="3" PreviewKeyDown="TbxIP1_PreviewKeyDown"PreviewKeyUp="TbxIP1_PreviewKeyUp" BorderThickness="0"><i:Interaction.Behaviors><keyboard:NumericKeyboardBehavior EnterText="{StaticResource Enter}" FocusedClearText="True" /></i:Interaction.Behaviors></TextBox><TextBox Grid.Column="2" Name="TbxIP2" HorizontalContentAlignment="Center" Background="Transparent"InputMethod.IsInputMethodEnabled="False" MaxLength="3" PreviewKeyDown="TbxIP1_PreviewKeyDown" PreviewKeyUp="TbxIP1_PreviewKeyUp" BorderThickness="0"><i:Interaction.Behaviors><keyboard:NumericKeyboardBehavior EnterText="{StaticResource Enter}" FocusedClearText="True" /></i:Interaction.Behaviors></TextBox><TextBox Grid.Column="4" Name="TbxIP3" HorizontalContentAlignment="Center" Background="Transparent" InputMethod.IsInputMethodEnabled="False" MaxLength="3" PreviewKeyDown="TbxIP1_PreviewKeyDown" PreviewKeyUp="TbxIP1_PreviewKeyUp" BorderThickness="0"><i:Interaction.Behaviors><keyboard:NumericKeyboardBehavior EnterText="{StaticResource Enter}" FocusedClearText="True" /></i:Interaction.Behaviors></TextBox><TextBox Grid.Column="6" Name="TbxIP4" HorizontalContentAlignment="Center" Background="Transparent" InputMethod.IsInputMethodEnabled="False"MaxLength="3" PreviewKeyDown="TbxIP1_PreviewKeyDown" PreviewKeyUp="TbxIP1_PreviewKeyUp" BorderThickness="0"><i:Interaction.Behaviors><keyboard:NumericKeyboardBehavior EnterText="{StaticResource Enter}" FocusedClearText="True" /></i:Interaction.Behaviors></TextBox><TextBlock Grid.Column="1" Text="." /><TextBlock Grid.Column="3" Text="."/><TextBlock Grid.Column="5" Text="."/></Grid></Border>
</UserControl>
cs
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;namespace 项目
{/// <summary>/// IPTextBox.xaml 的交互逻辑/// </summary>public partial class IPTextBox : UserControl{public IPTextBox(){InitializeComponent();}/// <summary>/// 按下按键键前,判断哪些能输入/// 只能输入数字 删除键 回车键 返回键 Tab键 左右方向键/// 删除键、左右方向键 控制光标位置/// </summary>private void TbxIP1_PreviewKeyDown(object sender, KeyEventArgs e){Key key = e.Key;if (sender is not TextBox tbx || tbx == null) { return; }if ((key >= Key.D0 && key <= Key.D9) || (key >= Key.NumPad0 && key <= Key.NumPad9)){}else if (key == Key.Delete){}else if (key == Key.Enter){}else if (key == Key.Back){// 删除光标前面的数字,如果光标前没有数字,会跳转到前面一个输入框// 先Focus到了前面一个输入框,再执行的删除操作,所以会删除前面输入框中的一个数字if (tbx?.CaretIndex == 0){SetTbxFocus(tbx, false, false);}}else if (key == Key.Tab){}else if (key == Key.Left){// 光标已经在当前输入框的最左边,则跳转到前面一个输入框if (tbx.CaretIndex == 0){SetTbxFocus(tbx, false, false);// 得设置true,不然光标在前面一个输入框里也会移动一次// 例如前一个输入框中的数字是123,Focus后,光标在数字3右边// 不设置true,会移动到数字2和数字3之间e.Handled = true;}}else if (key == Key.Right){// 光标已经在当前输入框的最右边,则跳转到后面一个输入框if (tbx.SelectionStart == tbx.Text.Length){SetTbxFocus(tbx, true, false);// true同理e.Handled = true;}}else{// 不是上述按键,就不处理e.Handled = true;}}/// <summary>/// 释放按键前,判断光标要做什么操作/// </summary>private void TbxIP1_PreviewKeyUp(object sender, KeyEventArgs e){Key key = e.Key;if (sender is not TextBox tbx || tbx == null) { return; }if ((key >= Key.D0 && key <= Key.D9) || (key >= Key.NumPad0 && key <= Key.NumPad9)){// 当前输入框满三个数字后// 跳转到后面一个输入框if (tbx.Text.Length == 3){if (Int32.Parse(tbx.Text) < 0 || Int32.Parse(tbx.Text) > 255){tbx.Text = "255";return;}SetTbxFocus(tbx, true, true);}}else if (key == Key.Delete){// 无操作}else if (key == Key.Enter){// 暂时不做操作}else if (key == Key.Back){}else if (key == Key.Tab){// 暂时不做操作}else if (key == Key.Left){}else if (key == Key.Right){}else{// 不是上述按键,就不处理e.Handled = true;}}/// <summary>/// 设置当前输入框的前面或后面的输入框获取焦点,以及是否全选内容/// </summary>/// <param name="curretTbx">当前输入框</param>/// <param name="isBack">是否是后面的输入框(false为前面的输入框)</param>/// <param name="isSelectAll">是否全选内容</param>private void SetTbxFocus(TextBox curretTbx, bool isBack, bool isSelectAll){// 所有的ip输入框var TbxIPList = new List<TextBox>();foreach (UIElement item in GridIPAddress.Children){if (item.GetType() != typeof(TextBox)){continue;}if (item is not TextBox tbx || tbx == null){continue;}TbxIPList.Add(tbx);}// 要聚焦的输入框TextBox? nextTbx = null;// 往后if (isBack){// 当前输入框是前三个,那么就取后一个输入框int index = TbxIPList.IndexOf(curretTbx);if (index <= 2){nextTbx = TbxIPList[index + 1];}}// 往前else{// 当前输入框是后三个,那么就取前一个输入框int index = TbxIPList.IndexOf(curretTbx);if (index >= 1){nextTbx = TbxIPList[index - 1];}}// 设置焦点 全选内容if (nextTbx != null){nextTbx.Focus();if (isSelectAll){nextTbx.SelectAll();}}}}
}