From 958cda81a79b376847dd0aa21e2c896217560aad Mon Sep 17 00:00:00 2001
From: NaBian <836904362@qq.com>
Date: Tue, 14 Jan 2020 01:25:29 +0800
Subject: [PATCH] add basic codes
---
.../UserControl/Controls/PinBoxDemoCtl.xaml | 6 +-
.../Controls/Input/PinBox.cs | 219 +++++++++++++++++-
.../Themes/Styles/Base/PinBoxBaseStyle.xaml | 15 +-
3 files changed, 236 insertions(+), 4 deletions(-)
diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PinBoxDemoCtl.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PinBoxDemoCtl.xaml
index 77c4a6f4..d5175cbc 100644
--- a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PinBoxDemoCtl.xaml
+++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/PinBoxDemoCtl.xaml
@@ -1,7 +1,9 @@
-
+
+
+
diff --git a/src/Shared/HandyControl_Shared/Controls/Input/PinBox.cs b/src/Shared/HandyControl_Shared/Controls/Input/PinBox.cs
index 86634976..addf3612 100644
--- a/src/Shared/HandyControl_Shared/Controls/Input/PinBox.cs
+++ b/src/Shared/HandyControl_Shared/Controls/Input/PinBox.cs
@@ -1,9 +1,226 @@
-using System.Windows.Controls;
+using System;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using HandyControl.Data;
+using HandyControl.Tools;
namespace HandyControl.Controls
{
+ [TemplatePart(Name = ElementPanel, Type = typeof(Panel))]
public class PinBox : Control
{
+ private const string ElementPanel = "PART_Panel";
+ private static readonly object MinLength = 4;
+
+ private Panel _panel;
+
+ private int _inputIndex;
+
+ private bool _changed;
+
+ private RoutedEventHandler _passwordBoxsGotFocusEventHandler;
+
+ private RoutedEventHandler _passwordBoxsPasswordChangedEventHandler;
+
+ public PinBox()
+ {
+ Loaded += PinBox_Loaded;
+ Unloaded += PinBox_Unloaded;
+ }
+
+ private void PinBox_Unloaded(object sender, RoutedEventArgs e)
+ {
+ RemoveHandler(System.Windows.Controls.PasswordBox.PasswordChangedEvent, _passwordBoxsPasswordChangedEventHandler);
+ RemoveHandler(GotFocusEvent, _passwordBoxsGotFocusEventHandler);
+
+ Loaded -= PinBox_Loaded;
+ Unloaded -= PinBox_Unloaded;
+ }
+
+ private void PinBox_Loaded(object sender, RoutedEventArgs e)
+ {
+ _passwordBoxsPasswordChangedEventHandler = PasswordBoxsPasswordChanged;
+ AddHandler(System.Windows.Controls.PasswordBox.PasswordChangedEvent, _passwordBoxsPasswordChangedEventHandler);
+
+ _passwordBoxsGotFocusEventHandler = PasswordBoxsGotFocus;
+ AddHandler(GotFocusEvent, _passwordBoxsGotFocusEventHandler);
+ }
+
+ private void PasswordBoxsPasswordChanged(object sender, RoutedEventArgs e)
+ {
+ if (e.OriginalSource is System.Windows.Controls.PasswordBox passwordBox)
+ {
+ if (passwordBox.Password.Length > 0)
+ {
+ if (++_inputIndex >= Length)
+ {
+ _inputIndex = Length - 1;
+
+ if (_panel.Children.OfType()
+ .All(item => item.Password.Any()))
+ {
+ FocusManager.SetFocusedElement(this, null);
+ Keyboard.ClearFocus();
+ RaiseEvent(new RoutedEventArgs(CompletedEvent, this));
+ }
+ return;
+ }
+ }
+ else
+ {
+ if (--_inputIndex < 0)
+ {
+ _inputIndex = 0;
+ return;
+ }
+ }
+
+ _changed = true;
+ FocusManager.SetFocusedElement(this, _panel.Children[_inputIndex]);
+ }
+ }
+
+ private void PasswordBoxsGotFocus(object sender, RoutedEventArgs e)
+ {
+ if (e.OriginalSource is System.Windows.Controls.PasswordBox passwordBox)
+ {
+ _inputIndex = _panel.Children.IndexOf(passwordBox);
+ }
+ }
+
+ protected override void OnPreviewKeyDown(KeyEventArgs e)
+ {
+ base.OnPreviewKeyUp(e);
+
+ if (e.Key == Key.Left)
+ {
+ if (--_inputIndex < 0)
+ {
+ _inputIndex = 0;
+ return;
+ }
+
+ FocusManager.SetFocusedElement(this, _panel.Children[_inputIndex]);
+ }
+ else if (e.Key == Key.Right)
+ {
+ if (++_inputIndex >= Length)
+ {
+ _inputIndex = Length - 1;
+ return;
+ }
+
+ FocusManager.SetFocusedElement(this, _panel.Children[_inputIndex]);
+ }
+ }
+
+ protected override void OnPreviewKeyUp(KeyEventArgs e)
+ {
+ base.OnPreviewKeyUp(e);
+
+ if (_changed)
+ {
+ _changed = false;
+ return;
+ }
+
+ if (e.Key == Key.Delete || e.Key == Key.Back)
+ {
+ if (--_inputIndex < 0)
+ {
+ _inputIndex = 0;
+ return;
+ }
+
+ FocusManager.SetFocusedElement(this, _panel.Children[_inputIndex]);
+ }
+ }
+
+ public static readonly DependencyProperty LengthProperty = DependencyProperty.Register(
+ "Length", typeof(int), typeof(PinBox), new PropertyMetadata(MinLength, null, CoerceLength), ValidateHelper.IsInRangeOfPosInt);
+
+ private static object CoerceLength(DependencyObject d, object basevalue) => (int)basevalue < 4 ? MinLength : basevalue;
+
+ public int Length
+ {
+ get => (int) GetValue(LengthProperty);
+ set => SetValue(LengthProperty, value);
+ }
+
+ public static readonly DependencyProperty ItemMarginProperty = DependencyProperty.Register(
+ "ItemMargin", typeof(Thickness), typeof(PinBox), new PropertyMetadata(default(Thickness)));
+
+ public Thickness ItemMargin
+ {
+ get => (Thickness) GetValue(ItemMarginProperty);
+ set => SetValue(ItemMarginProperty, value);
+ }
+
+ public static readonly DependencyProperty ItemWidthProperty = DependencyProperty.Register(
+ "ItemWidth", typeof(double), typeof(PinBox), new PropertyMetadata(ValueBoxes.Double0Box));
+
+ public double ItemWidth
+ {
+ get => (double) GetValue(ItemWidthProperty);
+ set => SetValue(ItemWidthProperty, value);
+ }
+
+ public static readonly DependencyProperty ItemHeightProperty = DependencyProperty.Register(
+ "ItemHeight", typeof(double), typeof(PinBox), new PropertyMetadata(ValueBoxes.Double0Box));
+
+ public double ItemHeight
+ {
+ get => (double) GetValue(ItemHeightProperty);
+ set => SetValue(ItemHeightProperty, value);
+ }
+
+ public static readonly RoutedEvent CompletedEvent =
+ EventManager.RegisterRoutedEvent("Completed", RoutingStrategy.Bubble,
+ typeof(EventHandler), typeof(PinBox));
+
+ public event EventHandler Completed
+ {
+ add => AddHandler(CompletedEvent, value);
+ remove => RemoveHandler(CompletedEvent, value);
+ }
+
+ private void UpdateItems()
+ {
+ _panel.Children.Clear();
+ var length = Length;
+
+ for (var i = 0; i < length; i++)
+ {
+ _panel.Children.Add(CreatePasswordBox());
+ }
+ }
+
+ private System.Windows.Controls.PasswordBox CreatePasswordBox()
+ {
+ return new System.Windows.Controls.PasswordBox
+ {
+ MaxLength = 1,
+ HorizontalContentAlignment = HorizontalAlignment.Center,
+ VerticalAlignment = VerticalAlignment.Center,
+ Margin = ItemMargin,
+ Width = ItemWidth,
+ Height = ItemHeight,
+ Padding = new Thickness()
+ };
+ }
+
+ public override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ _panel = GetTemplateChild(ElementPanel) as Panel;
+ if (_panel != null)
+ {
+ UpdateItems();
+ }
+ }
}
}
diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Base/PinBoxBaseStyle.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Base/PinBoxBaseStyle.xaml
index 98d80b3f..a81214d7 100644
--- a/src/Shared/HandyControl_Shared/Themes/Styles/Base/PinBoxBaseStyle.xaml
+++ b/src/Shared/HandyControl_Shared/Themes/Styles/Base/PinBoxBaseStyle.xaml
@@ -2,8 +2,21 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls">
-
\ No newline at end of file