91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

WPF自定義實現IP地址輸入控件

發布時間:2020-09-25 10:23:08 來源:腳本之家 閱讀:400 作者:一葉知秋,知寒冬 欄目:編程語言

一、前言

WPF沒有內置IP地址輸入控件,因此我們需要通過自己定義實現。

我們先看一下IP地址輸入控件有什么特性:

WPF自定義實現IP地址輸入控件

  • 輸滿三個數字焦點會往右移
  • 鍵盤←→可以空光標移動
  • 任意位置可復制整段IP地址,且支持x.x.x.x格式的粘貼賦值
  • 刪除字符會自動向左移動焦點

知道以上特性,我們就可以開始動手了。

二、構成

Grid+TextBox*4+TextBlock*3

通過這幾個控件的組合,我們完成IP地址輸入控件的功能。

界面代碼如下:

<UserControl
 x:Class="IpAddressControl.IpAddressControl"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 xmlns:local="clr-namespace:IpAddressControl"
 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 Margin="10,0"
 d:DesignHeight="50"
 d:DesignWidth="800"
 mc:Ignorable="d" Background="White">
 <UserControl.Resources>
  <ControlTemplate x:Key="validationTemplate">
   <DockPanel>
    <TextBlock
     Margin="1,2"
     DockPanel.Dock="Right"
     FontSize="{DynamicResource ResourceKey=Heading4}"
     FontWeight="Bold"
     Foreground="Red"
     Text="" />
    <AdornedElementPlaceholder />
   </DockPanel>
  </ControlTemplate>
  <Style x:Key="CustomTextBoxTextStyle" TargetType="TextBox">
   <Setter Property="MaxLength" Value="3" />
   <Setter Property="HorizontalAlignment" Value="Stretch" />
   <Setter Property="VerticalAlignment" Value="Center" />
   <Style.Triggers>
    <Trigger Property="Validation.HasError" Value="True">
     <Trigger.Setters>
      <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
      <Setter Property="BorderBrush" Value="Red" />
      <Setter Property="Background" Value="Red" />
     </Trigger.Setters>
    </Trigger>
   </Style.Triggers>
  </Style>
 </UserControl.Resources>
 <Grid>
  <Grid.ColumnDefinitions>
   <ColumnDefinition MinWidth="30" />
   <ColumnDefinition Width="10" />
   <ColumnDefinition MinWidth="30" />
   <ColumnDefinition Width="10" />
   <ColumnDefinition MinWidth="30" />
   <ColumnDefinition Width="10" />
   <ColumnDefinition MinWidth="30" />
  </Grid.ColumnDefinitions>

  <!-- Part 1 -->
  <TextBox
   Grid.Column="0"
   BorderThickness="0"
   HorizontalAlignment="Stretch"
   VerticalAlignment="Stretch"
   VerticalContentAlignment="Center"
   HorizontalContentAlignment="Center"
   x:Name="part1"
   PreviewKeyDown="Part1_PreviewKeyDown"
   local:FocusChangeExtension.IsFocused="{Binding IsPart1Focused, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}"
   Style="{StaticResource CustomTextBoxTextStyle}"
   Validation.ErrorTemplate="{StaticResource validationTemplate}">
   <TextBox.Text>
    <Binding Path="Part1" UpdateSourceTrigger="PropertyChanged">
     <Binding.ValidationRules>
      <local:IPRangeValidationRule Max="255" Min="0" />
     </Binding.ValidationRules>
    </Binding>
   </TextBox.Text>
  </TextBox>
  <TextBlock
   Grid.Column="1"
   HorizontalAlignment="Center"
   FontSize="15"
   Text="."
   VerticalAlignment="Center"
  />

  <!-- Part 2 -->
  <TextBox
   Grid.Column="2"
   x:Name="part2"
   BorderThickness="0"
   VerticalAlignment="Stretch"
   VerticalContentAlignment="Center"
   HorizontalContentAlignment="Center"
   PreviewKeyDown="Part2_KeyDown"
   local:FocusChangeExtension.IsFocused="{Binding IsPart2Focused}"
   Style="{StaticResource CustomTextBoxTextStyle}"
   Validation.ErrorTemplate="{StaticResource validationTemplate}">
   <TextBox.Text>
    <Binding Path="Part2" UpdateSourceTrigger="PropertyChanged">
     <Binding.ValidationRules>
      <local:IPRangeValidationRule Max="255" Min="0" />
     </Binding.ValidationRules>
    </Binding>
   </TextBox.Text>
  </TextBox>
  <TextBlock
   Grid.Column="3"
   HorizontalAlignment="Center"
   FontSize="15"
   Text="."
   VerticalAlignment="Center"/>

  <!-- Part 3 -->
  <TextBox
   Grid.Column="4"
   x:Name="part3"
   BorderThickness="0"
   VerticalAlignment="Stretch"
   VerticalContentAlignment="Center"
   HorizontalContentAlignment="Center"
   PreviewKeyDown="Part3_KeyDown"
   local:FocusChangeExtension.IsFocused="{Binding IsPart3Focused}"
   Style="{StaticResource CustomTextBoxTextStyle}"
   Validation.ErrorTemplate="{StaticResource validationTemplate}">
   <TextBox.Text>
    <Binding Path="Part3" UpdateSourceTrigger="PropertyChanged">
     <Binding.ValidationRules>
      <local:IPRangeValidationRule Max="255" Min="0" />
     </Binding.ValidationRules>
    </Binding>
   </TextBox.Text>
  </TextBox>
  <TextBlock
   Grid.Column="5"
   HorizontalAlignment="Center"
   FontSize="15"
   Text="."
   VerticalAlignment="Center"/>

  <!-- Part 4 -->
  <TextBox
   Grid.Column="6"
   x:Name="part4"
   BorderThickness="0"
   VerticalAlignment="Stretch"
   VerticalContentAlignment="Center"
   HorizontalContentAlignment="Center"
   PreviewKeyDown="Part4_KeyDown"
   local:FocusChangeExtension.IsFocused="{Binding IsPart4Focused}"
   Style="{StaticResource CustomTextBoxTextStyle}"
   Validation.ErrorTemplate="{StaticResource validationTemplate}">
   <TextBox.Text>
    <Binding Path="Part4" UpdateSourceTrigger="PropertyChanged">
     <Binding.ValidationRules>
      <local:IPRangeValidationRule Max="255" Min="0" />
     </Binding.ValidationRules>
    </Binding>
   </TextBox.Text>
  </TextBox>
 </Grid>
</UserControl>

三、驗證輸入格式

界面中為TextBox添加了CustomTextBoxTextStyle及validationTemplate樣式,當輸入格式不正確時,控件就會應用該樣式。

通過自定義規則IPRangeValidationRule來驗證輸入的內容格式是否要求。

自定義規則代碼如下:

public class IPRangeValidationRule : ValidationRule
{
 private int _min;
 private int _max;

 public int Min
 {
  get { return _min; }
  set { _min = value; }
 }

 public int Max
 {
  get { return _max; }
  set { _max = value; }
 }

 public override ValidationResult Validate(object value, CultureInfo cultureInfo)
 {
  int val = 0;
  var strVal = (string)value;
  try
  {
   if (strVal.Length > 0)
   {
    if (strVal.EndsWith("."))
    {
     return CheckRanges(strVal.Replace(".", ""));
    }

    // Allow dot character to move to next box
    return CheckRanges(strVal);
   }
  }
  catch (Exception e)
  {
   return new ValidationResult(false, "Illegal characters or " + e.Message);
  }

  if ((val < Min) || (val > Max))
  {
   return new ValidationResult(false,
    "Please enter the value in the range: " + Min + " - " + Max + ".");
  }
  else
  {
   return ValidationResult.ValidResult;
  }
 }

 private ValidationResult CheckRanges(string strVal)
 {
  if (int.TryParse(strVal, out var res))
  {
   if ((res < Min) || (res > Max))
   {
    return new ValidationResult(false,
     "Please enter the value in the range: " + Min + " - " + Max + ".");
   }
   else
   {
    return ValidationResult.ValidResult;
   }
  }
  else
  {
   return new ValidationResult(false, "Illegal characters entered");
  }
 }
}

四、控制焦點變化

在界面代碼中我通過local:FocusChangeExtension.IsFocused附加屬性實現綁定屬性控制焦點的變化。

附加屬性的代碼如下:

public static class FocusChangeExtension
{
 public static bool GetIsFocused(DependencyObject obj)
 {
  return (bool)obj.GetValue(IsFocusedProperty);
 }

 public static void SetIsFocused(DependencyObject obj, bool value)
 {
  obj.SetValue(IsFocusedProperty, value);
 }

 public static readonly DependencyProperty IsFocusedProperty =
  DependencyProperty.RegisterAttached(
   "IsFocused", typeof(bool), typeof(FocusChangeExtension),
   new UIPropertyMetadata(false, OnIsFocusedPropertyChanged));

 private static void OnIsFocusedPropertyChanged(
  DependencyObject d,
  DependencyPropertyChangedEventArgs e)
 {
  var control = (UIElement)d;
  if ((bool)e.NewValue)
  {
   control.Focus();
  }
 }
}

五、VM+后臺代碼混合實現焦點控制及內容復制粘貼

1、后臺代碼主要實現復制粘貼內容,另外←→移動光標也需要后臺代碼控制。通過PreviewKeyDown事件捕獲鍵盤左移右移,復制,刪除等事件,做出相應處理:

private void Part2_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
 if (e.Key == Key.Back && part2.Text == "")
 {
  part1.Focus();
 }
 if (e.Key == Key.Right && part2.CaretIndex == part2.Text.Length)
 {
  part3.Focus();
  e.Handled = true;
 }
 if (e.Key == Key.Left && part2.CaretIndex == 0)
 {
  part1.Focus();
  e.Handled = true;
 }

 if (e.KeyboardDevice.Modifiers.HasFlag(ModifierKeys.Control) && e.Key == Key.C)
 {
  if (part2.SelectionLength == 0)
  {
   var vm = this.DataContext as IpAddressViewModel;
   Clipboard.SetText(vm.AddressText);
  }
 }
}

通過DataObject.AddPastingHandler(part1, TextBox_Pasting)添加粘貼事件。使控件賦值。

2、通過ViewModel方式實現屬性綁定通知,來控制焦點變化及內容賦值。

ViewModel類要實現綁定通知需要實現INotifyPropertyChanged接口中的方法。

我們新建一個IpAddressViewModel類繼承INotifyPropertyChanged,代碼如下:

public class IpAddressViewModel : INotifyPropertyChanged
{
 public event EventHandler AddressChanged;

 public string AddressText
 {
  get { return $"{Part1??"0"}.{Part2??"0"}.{Part3??"0"}.{Part4??"0"}"; }
 }

 private bool isPart1Focused;

 public bool IsPart1Focused
 {
  get { return isPart1Focused; }
  set { isPart1Focused = value; OnPropertyChanged(); }
 }

 private string part1;

 public string Part1
 {
  get { return part1; }
  set
  {
   part1 = value;
   SetFocus(true, false, false, false);

   var moveNext = CanMoveNext(ref part1);

   OnPropertyChanged();
   OnPropertyChanged(nameof(AddressText));
   AddressChanged?.Invoke(this, EventArgs.Empty);

   if (moveNext)
   {
    SetFocus(false, true, false, false);
   }
  }
 }
 
 private bool isPart2Focused;

 public bool IsPart2Focused
 {
  get { return isPart2Focused; }
  set { isPart2Focused = value; OnPropertyChanged(); }
 }


 private string part2;

 public string Part2
 {
  get { return part2; }
  set
  {
   part2 = value;
   SetFocus(false, true, false, false);

   var moveNext = CanMoveNext(ref part2);

   OnPropertyChanged();
   OnPropertyChanged(nameof(AddressText));
   AddressChanged?.Invoke(this, EventArgs.Empty);

   if (moveNext)
   {
    SetFocus(false, false, true, false);
   }
  }
 }

 private bool isPart3Focused;

 public bool IsPart3Focused
 {
  get { return isPart3Focused; }
  set { isPart3Focused = value; OnPropertyChanged(); }
 }

 private string part3;

 public string Part3
 {
  get { return part3; }
  set
  {
   part3 = value;
   SetFocus(false, false, true, false);
   var moveNext = CanMoveNext(ref part3);

   OnPropertyChanged();
   OnPropertyChanged(nameof(AddressText));
   AddressChanged?.Invoke(this, EventArgs.Empty);

   if (moveNext)
   {
    SetFocus(false, false, false, true);
   }
  }
 }

 private bool isPart4Focused;

 public bool IsPart4Focused
 {
  get { return isPart4Focused; }
  set { isPart4Focused = value; OnPropertyChanged(); }
 }

 private string part4;

 public string Part4
 {
  get { return part4; }
  set
  {
   part4 = value;
   SetFocus(false, false, false, true);
   var moveNext = CanMoveNext(ref part4);

   OnPropertyChanged();
   OnPropertyChanged(nameof(AddressText));
   AddressChanged?.Invoke(this, EventArgs.Empty);

  }
 }
 
 public void SetAddress(string address)
 {
  if (string.IsNullOrWhiteSpace(address))
   return;

  var parts = address.Split('.');   

  if (int.TryParse(parts[0], out var num0))
  {
   Part1 = num0.ToString();
  }

  if (int.TryParse(parts[1], out var num1))
  {
   Part2 = parts[1];
  }

  if (int.TryParse(parts[2], out var num2))
  {
   Part3 = parts[2];
  }

  if (int.TryParse(parts[3], out var num3))
  {
   Part4 = parts[3];
  }

 }

 private bool CanMoveNext(ref string part)
 {
  bool moveNext = false;

  if (!string.IsNullOrWhiteSpace(part))
  {
   if (part.Length >= 3)
   {
    moveNext = true;
   }

   if (part.EndsWith("."))
   {
    moveNext = true;
    part = part.Replace(".", "");
   }
  }

  return moveNext;
 }

 private void SetFocus(bool part1, bool part2, bool part3, bool part4)
 {
  IsPart1Focused = part1;
  IsPart2Focused = part2;
  IsPart3Focused = part3;
  IsPart4Focused = part4;
 }

 public event PropertyChangedEventHandler PropertyChanged;


 protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
 {
  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
 }
}

到這里基本就完成了,生成控件然后到MainWindow中引用該控件

六、最終效果

WPF自定義實現IP地址輸入控件

————————————————————

代碼地址:https://github.com/cmfGit/IpAddressControl.git

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

垦利县| 大足县| 股票| 汤阴县| 安阳市| 井冈山市| 赤壁市| 延寿县| 二连浩特市| 桦甸市| 永清县| 青神县| 兴安盟| 永善县| 靖江市| 紫阳县| 凤城市| 宁乡县| 谢通门县| 集安市| 长乐市| 阜新| 财经| 吉木萨尔县| 永新县| 滕州市| 老河口市| 高州市| 临湘市| 开化县| 莲花县| 公主岭市| 定州市| 环江| 新乡县| 锡林浩特市| 临泽县| 六枝特区| 泸溪县| 乌兰浩特市| 佛坪县|