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();
                }
            }
        }
    }
}
相关推荐
秋月的私语12 小时前
Wpf程序屏幕居中问题修复全记录
wpf
我要打打代码12 小时前
WPF启动窗体的三种方式
wpf
R瑾安12 小时前
mysql集群部署(Mysql Group Replication)
数据库·mysql·wpf
c#上位机12 小时前
wpf中资源的使用
c#·wpf
Vae_Mars1 天前
WPF中的静态资源和动态资源
wpf
somethingGoWay1 天前
wpf 只能输入int类型的文本框
wpf
主宰者1 天前
WPF外部打开html文件
前端·html·wpf
code bean1 天前
【wpf】WPF 自定义控件绑定数据对象的最佳实践
wpf
code bean1 天前
【wpf】WPF开发避坑指南:单例模式中依赖注入导致XAML设计器崩溃的解决方案
单例模式·wpf