如何让.NET MAUI Entry仅接受大于0的整数输入?
.NET MAUI Entry 仅允许输入大于0整数的解决方案
针对你遇到的文本处理异常、光标错位等问题,以下提供两种可行的跨平台方案,优先适配Android,同时兼容iOS:
方案一:使用自定义行为(Behavior)
该方案逻辑集中、易于复用,通过拦截文本变更事件,过滤无效输入并修正光标位置,解决错位问题。
实现代码
using Microsoft.Maui.Controls; public class PositiveIntegerValidationBehavior : Behavior<Entry> { protected override void OnAttachedTo(Entry entry) { entry.TextChanged += OnEntryTextChanged; base.OnAttachedTo(entry); } protected override void OnDetachingFrom(Entry entry) { entry.TextChanged -= OnEntryTextChanged; base.OnDetachingFrom(entry); } private void OnEntryTextChanged(object sender, TextChangedEventArgs e) { var entry = sender as Entry; if (entry == null) return; // 保存当前光标位置与选中长度 int cursorPos = entry.CursorPosition; int selectionLen = entry.SelectionLength; // 过滤所有非数字字符 string filteredText = new string(e.NewTextValue.Where(char.IsDigit).ToArray()); // 处理开头多余的0(如"0012"转为"12") if (filteredText.Length > 1 && filteredText.StartsWith("0")) { filteredText = filteredText.TrimStart('0'); // 光标位置随文本缩短前移 if (cursorPos > 0) cursorPos = Math.Max(0, cursorPos - (filteredText.Length + 1 - filteredText.Length)); } // 确保输入为大于0的整数,空文本保持为空 if (!string.IsNullOrEmpty(filteredText) && long.TryParse(filteredText, out long value) && value <= 0) { filteredText = string.Empty; cursorPos = 0; } // 仅在文本实际变更时更新,避免循环触发事件 if (entry.Text != filteredText) { entry.Text = filteredText; // 恢复光标位置,防止错位 entry.CursorPosition = Math.Min(cursorPos, filteredText.Length); entry.SelectionLength = selectionLen; } } }
XAML用法
<Entry Placeholder="请输入大于0的整数"> <Entry.Behaviors> <local:PositiveIntegerValidationBehavior /> </Entry.Behaviors> </Entry>
方案二:平台特定自定义Entry
若Behavior仍存在输入法兼容性问题,可通过平台原生API实现更底层的输入控制,稳定性更强。
1. 共享项目定义自定义Entry
using Microsoft.Maui.Controls; public class CustomPositiveIntegerEntry : Entry { }
2. Android端实现(使用InputFilter)
// Platforms/Android/Handlers/CustomEntryHandler.cs using Android.Content; using Android.Text; using Microsoft.Maui.Controls.Platform; [assembly: Microsoft.Maui.Controls.HandlerFor(typeof(CustomPositiveIntegerEntry), typeof(CustomEntryHandler))] namespace YourAppNamespace.Platforms.Android.Handlers { public class CustomEntryHandler : EntryHandler { protected override void ConnectHandler(Android.Widget.EditText platformView) { base.ConnectHandler(platformView); // 设置输入过滤器 platformView.SetFilters(new IInputFilter[] { new PositiveIntegerFilter() }); } private class PositiveIntegerFilter : Java.Lang.Object, IInputFilter { public ICharSequence FilterFormatted(ICharSequence source, int start, int end, ISpanned dest, int dstart, int dend) { string newText = dest.ToString().Remove(dstart, dend - dstart).Insert(dstart, source.ToString().Substring(start, end - start)); // 过滤非数字 newText = new string(newText.Where(char.IsDigit).ToArray()); // 校验正整数规则 if (string.IsNullOrEmpty(newText)) return new Java.Lang.String(""); if (newText.StartsWith("0") && newText.Length > 1) newText = newText.TrimStart('0'); if (!string.IsNullOrEmpty(newText) && long.TryParse(newText, out long val) && val <= 0) return new Java.Lang.String(""); return new Java.Lang.String(newText); } } } }
3. iOS端实现(使用UITextFieldDelegate)
// Platforms/iOS/Handlers/CustomEntryHandler.cs using Microsoft.Maui.Controls.Platform; using UIKit; [assembly: Microsoft.Maui.Controls.HandlerFor(typeof(CustomPositiveIntegerEntry), typeof(CustomEntryHandler))] namespace YourAppNamespace.Platforms.iOS.Handlers { public class CustomEntryHandler : EntryHandler { protected override void ConnectHandler(UITextField platformView) { base.ConnectHandler(platformView); platformView.Delegate = new PositiveIntegerTextFieldDelegate(); } private class PositiveIntegerTextFieldDelegate : UITextFieldDelegate { public override bool ShouldChangeCharacters(UITextField textField, NSRange range, string replacementString) { string newText = textField.Text?.Remove((int)range.Location, (int)range.Length).Insert((int)range.Location, replacementString) ?? replacementString; // 过滤非数字 newText = new string(newText.Where(char.IsDigit).ToArray()); // 校验正整数规则 if (string.IsNullOrEmpty(newText)) { textField.Text = ""; return false; } if (newText.StartsWith("0") && newText.Length > 1) { newText = newText.TrimStart('0'); textField.Text = string.IsNullOrEmpty(newText) ? "" : newText; return false; } if (long.TryParse(newText, out long val) && val <= 0) { textField.Text = ""; return false; } return true; } } } }
XAML用法
<local:CustomPositiveIntegerEntry Placeholder="请输入大于0的整数" />
注意事项
- 若需限制输入长度,可在过滤逻辑中添加文本长度判断
- 测试时覆盖边缘场景:输入0、多个0、小数点、字母、负数等
内容的提问来源于stack exchange,提问作者Wasyster
相关产品推荐
相关产品推荐

