xmal
PS:因为是上位机,所以文本框里面写了键盘,如果不需要可删除。
cs
<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
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();
}
}
}
}
}