C# Maui暂时还没有TextBox,因为这个可以通过xaml样式实现,但是为了长期使用,自己写一个TextBox。
定义一个TextEventArgs- public class TextEventArgs : EventArgs
- {
- public string Text{ get; set; }
- public TextEventArgs(string text)
- {
- Text = text;
- }
- }
复制代码 PropertyManager和之前的例子一样,这里就不重复了。除非更新了新功能。
我的MauiProgram.cs中添加了自定义字体,这个在第一个MAUI 配置中说了,以后也不再重复了。自己去https://www.iconfont.cn/注册账号,添加自己喜欢的字体icon,然后下载下来覆盖项目中的IconFont.ttf- fonts.AddFont("IconFont.ttf", "IconFont");
复制代码
TextBox继承Border,以后所有自定义控件都继承于Border,不要用Frame了,因为这个在将来的未来会被淘汰。现在Border可以实现所有功能。- public class TextBox : Border
- {
- public static readonly BindableProperty TextProperty = BindableProperty.Create(
- nameof(Text), typeof(string), typeof(TextBox), null,
- BindingMode.TwoWay, propertyChanged: OnTextChanged);
- public static readonly BindableProperty IsPasswordProperty = BindableProperty.Create(
- nameof(IsPassword), typeof(bool), typeof(TextBox), false);
- public static readonly BindableProperty IsMultilineProperty = BindableProperty.Create(
- nameof(IsMultiline), typeof(bool), typeof(TextBox), false);
- public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(
- nameof(Placeholder), typeof(string), typeof(TextBox), null);
- public static readonly BindableProperty TextColorProperty = BindableProperty.Create(
- nameof(TextColor), typeof(Color), typeof(TextBox), Colors.Black);
- public static readonly BindableProperty TextSizeProperty = BindableProperty.Create(
- nameof(TextSize), typeof(double), typeof(TextBox), 15d);
- public static readonly BindableProperty IsReadOnlyProperty = BindableProperty.Create(
- nameof(IsReadOnly), typeof(bool), typeof(TextBox), false,
- propertyChanged: OnIsReadOnlyChanged);
- public static readonly BindableProperty CharacterSpacingProperty = BindableProperty.Create(
- nameof(CharacterSpacing), typeof(double), typeof(TextBox), 0d);
- public static readonly BindableProperty CornerRadiusProperty =
- BindableProperty.Create(nameof(CornerRadius), typeof(double), typeof(TextBox), 0d,
- propertyChanged: PropertyManager.CornerRadiusProperty);
- public static readonly BindableProperty IconTextProperty =
- BindableProperty.Create(nameof(IconText), typeof(string), typeof(TextBox), null);
- public static readonly BindableProperty IconTextColorProperty =
- BindableProperty.Create(nameof(IconTextColor), typeof(Color), typeof(TextBox), Colors.Gray);
- public static readonly BindableProperty IconTextFontSizeProperty =
- BindableProperty.Create(nameof(IconTextFontSize), typeof(double), typeof(TextBox), 22d);
- public static readonly BindableProperty IconFontFamilyProperty =
- BindableProperty.Create(nameof(IconFontFamily), typeof(string), typeof(TextBox), "IconFont");
- public event EventHandler<TextEventArgs>? ReturnPressed, EditingFinished;
- public string Text
- {
- get => (string)GetValue(TextProperty);
- set => SetValue(TextProperty, value);
- }
- public bool IsPassword
- {
- get => (bool)GetValue(IsPasswordProperty);
- set => SetValue(IsPasswordProperty, value);
- }
- public bool IsMultiline
- {
- get => (bool)GetValue(IsMultilineProperty);
- set => SetValue(IsMultilineProperty, value);
- }
- public string Placeholder
- {
- get => (string)GetValue(PlaceholderProperty);
- set => SetValue(PlaceholderProperty, value);
- }
- public Color TextColor
- {
- get => (Color)GetValue(TextColorProperty);
- set => SetValue(TextColorProperty, value);
- }
- public double TextSize
- {
- get => (double)GetValue(TextSizeProperty);
- set => SetValue(TextSizeProperty, value);
- }
- public bool IsReadOnly
- {
- get => (bool)GetValue(IsReadOnlyProperty);
- set => SetValue(IsReadOnlyProperty, value);
- }
- public double CharacterSpacing
- {
- get => (double)GetValue(CharacterSpacingProperty);
- set => SetValue(CharacterSpacingProperty, value);
- }
- public double CornerRadius
- {
- get => (double)GetValue(CornerRadiusProperty);
- set => SetValue(CornerRadiusProperty, value);
- }
- public string IconText
- {
- get => (string)GetValue(IconTextProperty);
- set => SetValue(IconTextProperty, value);
- }
- public Color IconTextColor
- {
- get => (Color)GetValue(IconTextColorProperty);
- set => SetValue(IconTextColorProperty, value);
- }
- public double IconTextFontSize
- {
- get => (double)GetValue(IconTextFontSizeProperty);
- set => SetValue(IconTextFontSizeProperty, value);
- }
- public string IconFontFamily
- {
- get => (string)GetValue(IconFontFamilyProperty);
- set => SetValue(IconFontFamilyProperty, value);
- }
- private static void OnTextChanged(BindableObject bindable, object oldValue, object newValue)
- {
- var tb = (TextBox)bindable;
- var newText = newValue as string ?? string.Empty;
- var oldText = oldValue as string ?? string.Empty;
- if (newText.Length > oldText.Length && tb.IsMultiline)
- {
- var addText = newText.Substring(oldText.Length);
- if (addText.Contains('\r') || addText.Contains('\n'))
- {
- //如果是回车换行,则触发ReturnPressed事件,安全派发到UI线程
- tb.Dispatcher.Dispatch(() => tb.ReturnPressed?.Invoke(tb, new TextEventArgs(newText)));
- }
- }
- }
- //动态更新IsReadOnly属性
- private static void OnIsReadOnlyChanged(BindableObject bindable, object oldValue, object newValue)
- {
- var tb = (TextBox)bindable;
- if (tb.grid.Children.Count == 0)
- return;
- if (tb.grid.Children[0] is InputView view)
- {
- view.IsReadOnly = (bool)newValue;
- view.Background = (bool)newValue ? Colors.WhiteSmoke : Colors.Transparent;
- }
- }
- private Grid grid;
- public TextBox()
- {
- grid = new Grid()
- {
- ColumnDefinitions = new ColumnDefinitionCollection
- {
- new ColumnDefinition { Width = GridLength.Star },
- new ColumnDefinition { Width = GridLength.Auto }
- },
- };
- // 设置布局
- this.Content = grid;
- this.StrokeThickness = 1;
- this.Stroke = Colors.LightGray;
- this.StrokeShape = new RoundRectangle() { CornerRadius = CornerRadius };
- this.Padding = new Thickness(0);
- //重载OnHandlerChanged中也可以初始化,构造函数会先于属性设置执行
- //Dispatcher.Dispatch(Init)也可以初始化
- this.Loaded += Init;
- }
- private void Init(object? sender, EventArgs e)
- {
- //凡是设置了propertyChanged的属性,都需要在这里手动初始化,因为Dispatcher.Dispatch/Loaded会在propertyChanged之后执行
- InputView edit = IsMultiline ?
- new Editor()
- {
- Margin = new Thickness(0),
- AutoSize = EditorAutoSizeOption.TextChanges,
- VerticalTextAlignment = TextAlignment.Start,
- } :
- new Entry()
- {
- Margin = new Thickness(0),
- VerticalTextAlignment = TextAlignment.Start,
- };
- edit.IsReadOnly = IsReadOnly;
- edit.Background = IsReadOnly ? Colors.WhiteSmoke : Colors.Transparent;
- grid.Children.Add(edit);
- edit.SetBinding(InputView.TextProperty, new Binding(nameof(Text), mode: BindingMode.TwoWay, source: this));
- edit.SetBinding(InputView.PlaceholderProperty, new Binding(nameof(Placeholder), mode: BindingMode.TwoWay, source: this));
- edit.SetBinding(InputView.TextColorProperty, new Binding(nameof(TextColor), mode: BindingMode.TwoWay, source: this));
- edit.SetBinding(InputView.FontSizeProperty, new Binding(nameof(TextSize), mode: BindingMode.TwoWay, source: this));
- edit.SetBinding(InputView.CharacterSpacingProperty, new Binding(nameof(CharacterSpacing), mode: BindingMode.TwoWay, source: this));
- if (edit is Entry entry)
- {
- edit.SetBinding(Entry.IsPasswordProperty, new Binding(nameof(IsPassword), mode: BindingMode.TwoWay, source: this));
- entry.Completed += (s, e) =>
- {
- ReturnPressed?.Invoke(this, new TextEventArgs(edit.Text));
- edit.Unfocus();
- };
- }
- edit.Unfocused += (s, e) =>
- {
- EditingFinished?.Invoke(this, new TextEventArgs(edit.Text));
- };
- if (IsPassword)
- {
- Label icon = new Label()
- {
- Text = IconText,
- FontFamily = IconFontFamily,
- FontSize = IconTextFontSize,
- TextColor = IconTextColor,
- VerticalTextAlignment = TextAlignment.Center,
- Margin = new Thickness(10, 0),
- };
- grid.Children.Add(icon);
- Grid.SetColumn(icon, 1);
- icon.SetBinding(Label.TextProperty, new Binding(nameof(IconText), mode: BindingMode.TwoWay, source: this));
- icon.SetBinding(Label.TextColorProperty, new Binding(nameof(IconTextColor), mode: BindingMode.TwoWay, source: this));
- icon.SetBinding(Label.FontSizeProperty, new Binding(nameof(IconTextFontSize), mode: BindingMode.TwoWay, source: this));
- icon.SetBinding(Label.FontFamilyProperty, new Binding(nameof(IconFontFamily), mode: BindingMode.TwoWay, source: this));
- TapGestureRecognizer tapGesture = new TapGestureRecognizer();
- tapGesture.Tapped += OnTapped;
- icon.GestureRecognizers.Add(tapGesture);
- }
- }
- private void OnTapped(object? sender, TappedEventArgs e)
- {
- Grid? grid = (sender as Label)?.Parent as Grid;
- if (grid == null)
- return;
- if (grid.Children[0] is Entry entry)
- {
- entry.IsPassword = !entry.IsPassword;
- }
- }
- }
复制代码 TextBox.xaml (前面的例子已经说明了如何把自定义控件,加到默认命名空间,以后也不再重复了)- <?xml version="1.0" encoding="utf-8" ?>
- <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
- x:Class="MauiViews.MauiDemos.Book._03.TextBox"
- Title="TextBox" HeightRequest="400" WidthRequest="300">
- <Grid RowDefinitions="auto,auto,auto, *">
- <TextBox Placeholder="单行输入-只读" CornerRadius="15" IsReadOnly="True"/>
- <TextBox Grid.Row="1" Placeholder="单行输入" ReturnPressed="TextBox_ReturnPressed" CornerRadius="15"/>
- <TextBox Grid.Row="2" Placeholder="密码输入" IsPassword="True" ReturnPressed="TextBox_ReturnPressed"
- IconText=""/>
- <TextBox Grid.Row="3" Placeholder="多行输入" IsMultiline="True" ReturnPressed="TextBox_ReturnPressed"/>
- </Grid>
- </ContentPage>
复制代码 对应的cs代码- using Shares.Utility;
- using System.Diagnostics;
- namespace MauiViews.MauiDemos.Book._03;
- public partial class TextBox : ContentPage
- {
- public TextBox()
- {
- InitializeComponent();
- }
- private void TextBox_ReturnPressed(object? sender, TextEventArgs e)
- {
- Trace.WriteLine($"TextBox_ReturnPressed: {e.Text}");
- }
- }
复制代码 运行效果
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |