基于WPF实现IP输入控件
作者:WPF开发者
这篇文章主要介绍了如何基于WPF实现简单的IP输入控件,文中的示例代码讲解详细,对我们学习或工作有一定帮助,需要的小伙伴可以参考一下
WPF 实现IP输入控件
- 框架使用
.NET4 至 .NET6
; Visual Studio 2022
;
使用Grid来分为七列
- TextBox控件PART_TextBox1位于第一列。
- TextBox控件PART_TextBox2位于第三列。
- TextBox控件PART_TextBox3位于第五列。
- TextBox控件PART_TextBox4位于第七列。
实现代码
1)新增 IPEditBox.cs
代码如下:
TextBox1_TextChanged方法:当TextBox1的文本发生变化时触发。如果TextBox1中的文本长度大于等于3,焦点将转移到TextBox2,并调用UpdateText方法更新Text。
TextBox2_TextChanged方法:当TextBox2的文本发生变化时触发。如果TextBox2中的文本长度大于等于3,焦点将转移到TextBox3,并调用UpdateText方法更新Text。
TextBox3_TextChanged方法:当TextBox3的文本发生变化时触发。如果TextBox3中的文本长度大于等于3,焦点将转移到TextBox4,并调用UpdateText方法更新Text。
TextBox4_TextChanged方法:当TextBox4的文本发生变化时触发。无论文本长度如何,并调用UpdateText方法更新Text。
监听TextBox1、2、3、4控件的PreviewKeyDown事件处理。
- 是否按下Ctrl+V键组合(粘贴快捷键),
- 如果是,则调用ClipboardHandle()方法,并将事件参数的Handled属性设置为true。
- PasteTextIPTextBox方法负责处理粘贴的文本。如果粘贴的文本为空或只包含空白字符,则清除四个TextBox控件(_textBox1、_textBox2、_textBox3、_textBox4)的内容。否则,它通过句点('.')将文本分割,并将每个部分分配给_textboxBoxes数组中对应的TextBox控件。
监听TextBox1、2、3、4控件的Loaded事件处理。在TextBox加载完成时,通过CommandManager的AddPreviewExecutedHandler方法将TextBox的PreviewExecuted事件与TextBox_PreviewExecuted方法关联
- 如果执行的是复制(ApplicationCommands.Copy),则将_textBox1、_textBox2、_textBox3、_textBox4四个TextBox控件中的文本合并成一个IP地址字符串,并将该字符串设置为剪贴板的文本内容并更新Text。
- 如果是粘贴命令则将调用ClipboardHandle()方法。
using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace WPFDevelopers.Controls { [TemplatePart(Name = TextBox1TemplateName, Type = typeof(TextBox))] [TemplatePart(Name = TextBox2TemplateName, Type = typeof(TextBox))] [TemplatePart(Name = TextBox3TemplateName, Type = typeof(TextBox))] [TemplatePart(Name = TextBox4TemplateName, Type = typeof(TextBox))] public class IPEditBox : Control { private const string TextBox1TemplateName = "PART_TextBox1"; private const string TextBox2TemplateName = "PART_TextBox2"; private const string TextBox3TemplateName = "PART_TextBox3"; private const string TextBox4TemplateName = "PART_TextBox4"; public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(IPEditBox), new PropertyMetadata(string.Empty, OnTextChanged)); private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ctrl = d as IPEditBox; if (e.NewValue is string text && !ctrl._isChangingText) ctrl.PasteTextIPTextBox(text); } private TextBox _textBox1, _textBox2, _textBox3, _textBox4; private bool _isChangingText = false; public override void OnApplyTemplate() { base.OnApplyTemplate(); _textBox1 = GetTemplateChild(TextBox1TemplateName) as TextBox; if (_textBox1 != null) { _textBox1.TextChanged -= TextBox1_TextChanged; _textBox1.TextChanged += TextBox1_TextChanged; _textBox1.PreviewKeyDown -= TextBox_PreviewKeyDown; _textBox1.PreviewKeyDown += TextBox_PreviewKeyDown; _textBox1.Loaded -= TextBox_Loaded; _textBox1.Loaded += TextBox_Loaded; } _textBox2 = GetTemplateChild(TextBox2TemplateName) as TextBox; if (_textBox2 != null) { _textBox2.TextChanged -= TextBox2_TextChanged; _textBox2.TextChanged += TextBox2_TextChanged; _textBox2.PreviewKeyDown -= TextBox_PreviewKeyDown; _textBox2.PreviewKeyDown += TextBox_PreviewKeyDown; _textBox2.Loaded -= TextBox_Loaded; ; _textBox2.Loaded += TextBox_Loaded; } _textBox3 = GetTemplateChild(TextBox3TemplateName) as TextBox; if (_textBox3 != null) { _textBox3.TextChanged -= TextBox3_TextChanged; _textBox3.TextChanged += TextBox3_TextChanged; _textBox3.PreviewKeyDown -= TextBox_PreviewKeyDown; _textBox3.PreviewKeyDown += TextBox_PreviewKeyDown; _textBox3.Loaded -= TextBox_Loaded; _textBox3.Loaded += TextBox_Loaded; } _textBox4 = GetTemplateChild(TextBox4TemplateName) as TextBox; _textBox4.TextChanged -= TextBox4_TextChanged; _textBox4.TextChanged += TextBox4_TextChanged; _textBox4.PreviewKeyDown -= TextBox_PreviewKeyDown; _textBox4.PreviewKeyDown += TextBox_PreviewKeyDown; _textBox4.Loaded -= TextBox_Loaded; _textBox4.Loaded += TextBox_Loaded; } private void TextBox1_TextChanged(object sender, TextChangedEventArgs e) { if (_textBox1.Text.ToString().Length >= 3) _textBox2.Focus(); UpdateText(); } private void TextBox2_TextChanged(object sender, TextChangedEventArgs e) { if (_textBox2.Text.ToString().Length >= 3) _textBox3.Focus(); UpdateText(); } private void TextBox3_TextChanged(object sender, TextChangedEventArgs e) { if (_textBox3.Text.ToString().Length >= 3) _textBox4.Focus(); UpdateText(); } private void TextBox4_TextChanged(object sender, TextChangedEventArgs e) { UpdateText(); } void TextBox_Loaded(object sender, RoutedEventArgs e) { CommandManager.AddPreviewExecutedHandler((sender as TextBox), TextBox_PreviewExecuted); } void TextBox_PreviewExecuted(object sender, ExecutedRoutedEventArgs e) { if (e.Command == ApplicationCommands.Paste) { ClipboardHandle(); UpdateText(); e.Handled = true; } else if (e.Command == ApplicationCommands.Copy) { var ip = $"{_textBox1.Text}.{_textBox2.Text}.{_textBox3.Text}.{_textBox4.Text}"; Clipboard.SetText(ip); e.Handled = true; } } void ClipboardHandle() { var data = Clipboard.GetDataObject(); if (data.GetDataPresent(DataFormats.Text)) { var text = (string)data.GetData(DataFormats.UnicodeText); PasteTextIPTextBox(text); } } void TextBox_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.KeyboardDevice.Modifiers.HasFlag(ModifierKeys.Control) && e.Key == Key.V) { ClipboardHandle(); _isChangingText = false; e.Handled = true; } else if (e.Key == Key.Delete || e.Key == Key.Back) { _isChangingText = true; } else _isChangingText = false; } void PasteTextIPTextBox(string text) { _textBox1.TextChanged -= TextBox1_TextChanged; _textBox2.TextChanged -= TextBox2_TextChanged; _textBox3.TextChanged -= TextBox3_TextChanged; _textBox4.TextChanged -= TextBox4_TextChanged; if (string.IsNullOrWhiteSpace(text)) { _textBox1.Text = string.Empty; _textBox2.Text = string.Empty; _textBox3.Text = string.Empty; _textBox4.Text = string.Empty; } else { var strs = text.Split('.'); var _textboxBoxes = new TextBox[] { _textBox1, _textBox2, _textBox3, _textBox4 }; for (short i = 0; i < _textboxBoxes.Length; i++) { var str = i < strs.Length ? strs[i] : string.Empty; _textboxBoxes[i].Text = str; } } _textBox1.TextChanged += TextBox1_TextChanged; _textBox2.TextChanged += TextBox2_TextChanged; _textBox3.TextChanged += TextBox3_TextChanged; _textBox4.TextChanged += TextBox4_TextChanged; } void UpdateText() { var segments = new string[4] { _textBox1.Text.Trim(), _textBox2.Text.Trim(), _textBox3.Text.Trim(), _textBox4.Text.Trim() }; var allEmpty = segments.All(string.IsNullOrEmpty); if (allEmpty) { SetValue(TextProperty, string.Empty); return; } var noEmpty = segments.Where(s => !string.IsNullOrWhiteSpace(s)); if (noEmpty.Count() != 4) return; var ip = string.Join(".", noEmpty); if (ip != Text) SetValue(TextProperty, ip); } } }
2)新增 ColorPicker.xaml
代码如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:WPFDevelopers.Controls" xmlns:helpers="clr-namespace:WPFDevelopers.Helpers"> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Basic/ControlBasic.xaml" /> </ResourceDictionary.MergedDictionaries> <Style x:Key="WD.IPEditBox" BasedOn="{StaticResource WD.ControlBasicStyle}" TargetType="{x:Type controls:IPEditBox}"> <Setter Property="BorderThickness" Value="1" /> <Setter Property="BorderBrush" Value="{DynamicResource WD.BaseSolidColorBrush}" /> <Setter Property="Background" Value="{DynamicResource WD.BackgroundSolidColorBrush}" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="HorizontalContentAlignment" Value="Stretch" /> <Setter Property="Padding" Value="{StaticResource WD.DefaultPadding}" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type controls:IPEditBox}"> <ControlTemplate.Resources> <Style BasedOn="{StaticResource WD.DefaultTextBox}" TargetType="{x:Type TextBox}"> <Setter Property="BorderThickness" Value="0" /> <Setter Property="helpers:TextBoxHelper.AllowOnlyNumericInput" Value="True" /> <Setter Property="helpers:TextBoxHelper.MaxValue" Value="255" /> <Setter Property="helpers:TextBoxHelper.MinValue" Value="0" /> <Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="HorizontalContentAlignment" Value="Center" /> </Style> <Style TargetType="TextBlock"> <Setter Property="Text" Value="." /> <Setter Property="VerticalAlignment" Value="Center" /> </Style> </ControlTemplate.Resources> <Border x:Name="Root" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{Binding Path=(helpers:ElementHelper.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" UseLayoutRounding="{TemplateBinding UseLayoutRounding}"> <ScrollViewer HorizontalScrollBarVisibility="Auto"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="Auto" /> <ColumnDefinition /> <ColumnDefinition Width="Auto" /> <ColumnDefinition /> <ColumnDefinition Width="Auto" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <TextBox x:Name="PART_TextBox1" /> <TextBlock Grid.Column="1" /> <TextBox x:Name="PART_TextBox2" Grid.Column="2" /> <TextBlock Grid.Column="3" /> <TextBox x:Name="PART_TextBox3" Grid.Column="4" /> <TextBlock Grid.Column="5" /> <TextBox x:Name="PART_TextBox4" Grid.Column="6" /> </Grid> </ScrollViewer> </Border> <ControlTemplate.Triggers> <Trigger Property="IsKeyboardFocused" Value="True"> <Setter Property="BorderBrush" Value="{DynamicResource WD.PrimaryNormalSolidColorBrush}" /> </Trigger> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="BorderBrush" Value="{DynamicResource WD.PrimaryNormalSolidColorBrush}" /> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsKeyboardFocused" Value="True" /> <Condition Property="IsMouseOver" Value="False" /> </MultiTrigger.Conditions> <Setter Property="BorderBrush" Value="{DynamicResource WD.PrimaryNormalSolidColorBrush}" /> </MultiTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style BasedOn="{StaticResource WD.IPEditBox}" TargetType="{x:Type controls:IPEditBox}" /> </ResourceDictionary>
效果图
以上就是基于WPF实现IP输入控件的详细内容,更多关于WPF IP输入的资料请关注脚本之家其它相关文章!