wpf 自定义输入ip地址的文本框

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();
                }
            }
        }
    }
}
相关推荐
mingupup3 小时前
WPF/C#:使用Microsoft Agent Framework框架创建一个带有审批功能的终端Agent
c#·wpf
△曉風殘月〆6 小时前
WPF中的变换(Transform)功能详解
wpf
mingupup6 小时前
为WPF应用增加项目图标
wpf
张人玉9 小时前
c#WPF基础知识
开发语言·c#·wpf
yantuguiguziPGJ19 小时前
WPF 联合 Web 开发调试流程梳理(基于 Microsoft.Web.WebView2)
前端·microsoft·wpf
Aevget19 小时前
DevExpress WPF中文教程:Data Grid - 如何使用虚拟源?(二)
.net·wpf·界面控件·devexpress·ui开发·数据网格
大美B端工场-B端系统美颜师1 天前
工控软件开发选择难?Electron、Qt、WPF 对比
qt·electron·wpf
c#上位机1 天前
MefBootstrapper在Prism引导程序中的使用
c#·wpf·prism
没有bug.的程序员2 天前
服务治理与 API 网关:微服务流量管理的艺术
java·分布式·微服务·架构·wpf
Brianna Home2 天前
【案例实战】鸿蒙分布式调度:跨设备协同实战
华为·wpf·harmonyos