diff --git a/demo/Ursa.Demo/Pages/NumPadDemo.axaml b/demo/Ursa.Demo/Pages/NumPadDemo.axaml
index dbd997a..2e657ec 100644
--- a/demo/Ursa.Demo/Pages/NumPadDemo.axaml
+++ b/demo/Ursa.Demo/Pages/NumPadDemo.axaml
@@ -21,11 +21,21 @@
HorizontalAlignment="Stretch"
u:NumPad.Attach="True"
Watermark="Invoke NumPad" />
-
+
+ Watermark="Invoke u:NumericIntUpDown" />
+
+
+
diff --git a/src/Ursa.Themes.Semi/Controls/NumPad.axaml b/src/Ursa.Themes.Semi/Controls/NumPad.axaml
index e2aed73..372f7d3 100644
--- a/src/Ursa.Themes.Semi/Controls/NumPad.axaml
+++ b/src/Ursa.Themes.Semi/Controls/NumPad.axaml
@@ -92,7 +92,7 @@
+
+ /// ǷʹС
+ ///
+ internal bool IsTargetByNumPad
+ {
+ set
+ {
+ if(_isTargetByNumPad
+ &&!value)
+ {
+ SetLostFocus();
+ }
+ _isTargetByNumPad =value;
+ }
+ get => _isTargetByNumPad;
+ }
+ private bool _isTargetByNumPad;
+
#region Overrides
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
@@ -308,6 +326,15 @@ public class IPv4Box: TemplatedControl
protected override void OnLostFocus(RoutedEventArgs e)
{
base.OnLostFocus(e);
+ if (IsTargetByNumPad)
+ {
+ return;
+ }
+ SetLostFocus();
+ }
+
+ private void SetLostFocus()
+ {
foreach (var pre in _presenters)
{
pre?.HideCaret();
@@ -317,7 +344,8 @@ public class IPv4Box: TemplatedControl
ParseBytes(ShowLeadingZero);
SetIPAddressInternal();
}
-
+
+
protected override void OnGotFocus(GotFocusEventArgs e)
{
_currentActivePresenter = _firstText;
diff --git a/src/Ursa/Controls/NumPad/NumPad.cs b/src/Ursa/Controls/NumPad/NumPad.cs
index 3777dab..6f81bb7 100644
--- a/src/Ursa/Controls/NumPad/NumPad.cs
+++ b/src/Ursa/Controls/NumPad/NumPad.cs
@@ -1,6 +1,9 @@
using Avalonia;
+using Avalonia.Controls;
using Avalonia.Controls.Primitives;
+using Avalonia.Controls.Templates;
using Avalonia.Input;
+using Avalonia.LogicalTree;
using Irihi.Avalonia.Shared.Helpers;
namespace Ursa.Controls;
@@ -16,6 +19,11 @@ public class NumPad: TemplatedControl
set => SetValue(TargetProperty, value);
}
+ ///
+ /// Target Ŀڲ TextBox TextPresenter ؼ
+ ///
+ private TextBox? _targetInnerText;
+
public static readonly StyledProperty NumModeProperty = AvaloniaProperty.Register(
nameof(NumMode), defaultValue: true);
@@ -54,10 +62,24 @@ public class NumPad: TemplatedControl
var existing = OverlayDialog.Recall(null);
if (existing is not null)
{
+ if(existing.Target is IPv4Box pv4Box)
+ {
+ pv4Box.IsTargetByNumPad = false; // ȡ IPv4Box NumPad ģʽ
+ }
existing.Target = sender as InputElement;
+ existing._targetInnerText = FindTextBoxInTarget((sender as InputElement)!);
+
+ if (existing.Target is IPv4Box pv4Box2)
+ {
+ pv4Box2.IsTargetByNumPad = true;
+ }
return;
}
- var numPad = new NumPad() { Target = sender as InputElement };
+ var numPad = new NumPad()
+ {
+ Target = sender as InputElement ,
+ _targetInnerText = FindTextBoxInTarget((sender as InputElement)!)
+ };
OverlayDialog.Show(numPad, new object(), options: new OverlayDialogOptions() { Buttons = DialogButton.None });
}
@@ -84,9 +106,12 @@ public class NumPad: TemplatedControl
{
if (Target is null || o is not NumPadButton b) return;
var key = (b.NumMode ? b.NumKey : b.FunctionKey)?? Key.None;
+
+ // ڲΪ TextBox Ŀؼʹø TextBox ΪĿ
+ var realTarget = _targetInnerText ?? Target;
if (KeyInputMapping.TryGetValue(key, out var s))
{
- Target.RaiseEvent(new TextInputEventArgs()
+ realTarget.RaiseEvent(new TextInputEventArgs()
{
Source = this,
RoutedEvent = TextInputEvent,
@@ -95,7 +120,7 @@ public class NumPad: TemplatedControl
}
else
{
- Target.RaiseEvent(new KeyEventArgs()
+ realTarget.RaiseEvent(new KeyEventArgs()
{
Source = this,
RoutedEvent = KeyDownEvent,
@@ -103,4 +128,33 @@ public class NumPad: TemplatedControl
});
}
}
+ ///
+ /// Ŀؼв TextBox ؼ
+ ///
+ /// Ŀؼ
+ /// ҵ TextBoxûҵ null
+ private static TextBox? FindTextBoxInTarget(InputElement target)
+ {
+ // Ŀ걾 TextBox
+ if (target is TextBox textBox)
+ return textBox;
+
+ // Ŀ TemplatedControlѾӦģ
+ if (target is TemplatedControl templatedControl && templatedControl.IsInitialized)
+ {
+ // ͨģ PART_TextBox
+ if (templatedControl.GetTemplateChildren().FirstOrDefault(c => c is TextBox) is TextBox partTextBox)
+ return partTextBox;
+ }
+
+ // Ŀ ILogicalʹ LogicalTree չ
+ if (target is ILogical logical)
+ {
+ // ʹ GetLogicalDescendants ӿؼ
+ var textBoxes = logical.GetLogicalDescendants().OfType();
+ return textBoxes.FirstOrDefault();
+ }
+
+ return null;
+ }
}
\ No newline at end of file