TextBoxExtensions
类型通过扩展方法和附加属性为 TextBox
控件提供额外功能。
文本正则表达式
Regex
附加属性可用于使用正则表达式或使用内置验证类型进行文本验证。
开发人员可以通过添加正则表达式,根据正则表达式验证 TextBox 文本,方法是使用 Regex 属性,或者在 TextBox 上选择 ValidationType 属性。
有 3 种验证模式 (TextBoxExtensions.ValidationMode
):
Normal
(默认模式):此模式会根据Regex
属性判断TextBox
文本有效与否,将附加属性IsValid
相应设置为false
或true
。Forced
:此模式会设置IsValid
属性,并在TextBox
失去焦点时删除TextBox
文本(如果无效)。Dynamic
:此模式扩展了Normal
,并在TextBox
的最新输入无效时删除无效字符。 请注意,TextBoxExtensions.ValidationType
值Email
和PhoneNumber
不支持此验证模式。 如果验证模式设置为Dynamic
, 则会自动选择Normal
。
<Page x:Class="ExtensionsExperiment.Samples.TextBoxExtensions.RegexSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:CommunityToolkit.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:CommunityToolkit.WinUI"
mc:Ignorable="d">
<Page.Resources>
<Style x:Key="TextBoxRegexStyle"
TargetType="TextBox">
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
<DataTemplate x:Key="HeaderTemplate">
<StackPanel>
<TextBlock Text="{Binding}"
TextWrapping="WrapWholeWords" />
</StackPanel>
</DataTemplate>
</Page.Resources>
<Grid>
<Grid RowSpacing="32">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel>
<TextBox Name="PhoneNumberValidator"
ui:TextBoxExtensions.Regex="^\s*\+?\s*([0-9][\s-]*){9,}$"
Header="Text box with Regex extension for phone number, validation occurs on TextChanged"
HeaderTemplate="{StaticResource HeaderTemplate}"
Style="{StaticResource TextBoxRegexStyle}" />
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}">
<Run Text="Is valid: " />
<Run FontWeight="SemiBold"
Text="{Binding (ui:TextBoxExtensions.IsValid), ElementName=PhoneNumberValidator}" />
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="1">
<TextBox Name="CharactValidator"
ui:TextBoxExtensions.ValidationMode="Dynamic"
ui:TextBoxExtensions.ValidationType="Characters"
Header="Text box with ValidationType=Characters, validation occurs at input with ValidationMode=Dynamic and clear only single character when value is invalid"
HeaderTemplate="{StaticResource HeaderTemplate}"
Style="{StaticResource TextBoxRegexStyle}"
Text="abcdef" />
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}">
<Run Text="Is valid: " />
<Run FontWeight="SemiBold"
Text="{Binding (ui:TextBoxExtensions.IsValid), ElementName=CharactValidator}" />
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="2">
<TextBox Name="EmailValidator"
ui:TextBoxExtensions.ValidationType="Email"
Header="Text box with ValidationType=Email, validation occurs on TextChanged"
HeaderTemplate="{StaticResource HeaderTemplate}"
Style="{StaticResource TextBoxRegexStyle}" />
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}">
<Run Text="Is valid: " />
<Run FontWeight="SemiBold"
Text="{Binding (ui:TextBoxExtensions.IsValid), ElementName=EmailValidator}" />
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="3">
<TextBox Name="DecimalValidatorForce"
ui:TextBoxExtensions.ValidationMode="Forced"
ui:TextBoxExtensions.ValidationType="Decimal"
Header="Text box with ValidationType=Decimal, validation occurs on TextChanged and force occurs on lose focus with ValidationMode=Force (333,111 or 333.111)"
HeaderTemplate="{StaticResource HeaderTemplate}"
Style="{StaticResource TextBoxRegexStyle}" />
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}">
<Run Text="Is valid: " />
<Run FontWeight="SemiBold"
Text="{Binding (ui:TextBoxExtensions.IsValid), ElementName=DecimalValidatorForce}" />
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="4">
<TextBox Name="NumberValidatorDynamic"
ui:TextBoxExtensions.ValidationMode="Dynamic"
ui:TextBoxExtensions.ValidationType="Number"
Header="Text box with ValidationType=Number, validation occurs at input with ValidationMode=Dynamic and clear only single character when value is invalid"
HeaderTemplate="{StaticResource HeaderTemplate}"
Style="{StaticResource TextBoxRegexStyle}" />
<TextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}">
<Run Text="Is valid: " />
<Run FontWeight="SemiBold"
Text="{Binding (ui:TextBoxExtensions.IsValid), ElementName=NumberValidatorDynamic}" />
</TextBlock>
</StackPanel>
</Grid>
</Grid>
</Page>
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace ExtensionsExperiment.Samples.TextBoxExtensions;
[ToolkitSample(id: nameof(RegexSample), "Regex Extension", description: "A sample for showing how to use the Regex Extension.")]
public sealed partial class RegexSample : Page
{
public RegexSample()
{
this.InitializeComponent();
}
}
文本掩码
Mask
附加属性允许用户更轻松地在 TextBox
控件中输入固定宽度的文本,并采用你所期望的特定数据输入格式(例如电话号码、邮政编码)。
开发人员可添加掩码属性,防止最终用户输入所需格式(例如,“aaa-9999”格式的邮政编码)之外的任何其他格式。
Mask
属性提供的 3 个内置可变字符可用于定义掩码:
a
表示 [a-Z]9
表示 [0-9]*
表示a
或9
在邮政编码示例中,对于前 3 个字符,用户只能输入 a
至 Z
之间的字符;然后是一个固定字符 -
,用户可以更改或删除;对于最后一部分,用户可以进行更改,在每个字符位输入 0
至 9
之间的字符。 Mask
属性可防止 TextBox
包含非指定字符(例如,用户在类似 9999
的掩码处输入 1
或 2
)。
Mask
属性还支持 2 种字符类型:
- 可变:用户可以更改,如
a,9,*
- 固定:用户无法更改的任何非可变字符(例如第一个示例中的
-
)
可变字符以占位符形式展现给最终用户,以便用户可以知道哪些字符可以更改,哪些字符无法更改,例如,aaa-9999 将以 ___-____
的形式呈现给用户。 默认占位符是 _
,但可以使用 MaskPlaceholder
属性更改。
可以使用 \
来对可变字符进行转义(例如,掩码 +\964
将以 +964
的形式展现给用户)。 这样,掩码中的 9
将被视为固定字符,而非可变字符。 如果需要在掩码中使用 \
,可以将其表示为 \\
(例如,99\\99\\9999
将以 __\__\__
的形式展现给用户)。
如果要添加自定义变量字符,可以使用 CustomMask
属性。 可以添加一个字符,表示类似 c:[a-c]
的正则表达式,一旦在掩码中使用字符 c
,掩码将阻止 TextBox
中出现 a
至 c
之间的任何字符;另外,还可以通过在每个字符及其表示形式后添加逗号 ,
来指定多个可变字符。 如果希望允许某些语言的字符,此功能非常有用。(例如,法语或阿拉伯语才有的 TextBox
)。
<Page x:Class="ExtensionsExperiment.Samples.TextBoxExtensions.TextBoxMaskSample"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
mc:Ignorable="d">
<Page.Resources>
<Style x:Key="MaskedTextBoxStyle"
TargetType="TextBox">
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
<DataTemplate x:Key="HeaderTemplate">
<StackPanel>
<TextBlock Text="{Binding}"
TextWrapping="WrapWholeWords" />
</StackPanel>
</DataTemplate>
</Page.Resources>
<Grid>
<StackPanel Spacing="24">
<TextBox ui:TextBoxExtensions.Mask="9a9a-a9a*"
Header="Text box with Mask 9a9a-a9a* (9 allows from 0 to 9, a allow from a to Z and * allows both a and 9)"
HeaderTemplate="{StaticResource HeaderTemplate}"
Style="{StaticResource MaskedTextBoxStyle}"
Text="TextBoxMask" />
<TextBox ui:TextBoxExtensions.Mask="+1999-9999"
ui:TextBoxExtensions.MaskPlaceholder=" "
Header="Text box with Mask +1999-9999 and placeHolder as space (placeholder represents the characters the user can change on runtime)"
HeaderTemplate="{StaticResource HeaderTemplate}"
Style="{StaticResource MaskedTextBoxStyle}" />
<TextBox ui:TextBoxExtensions.Mask="+\964 799 999 9999"
Header="Text box with Mask +964 799 999 9999 (Notice how we escape the first 9 with a backslash)"
HeaderTemplate="{StaticResource HeaderTemplate}"
Style="{StaticResource MaskedTextBoxStyle}" />
<TextBox ui:TextBoxExtensions.Mask="99\\99\\9999"
Header="Text box with Mask 99\99\9999 (You can escape a backslash with another backslash)"
HeaderTemplate="{StaticResource HeaderTemplate}"
Style="{StaticResource MaskedTextBoxStyle}" />
<TextBox ui:TextBoxExtensions.CustomMask="5:[1-5],c:[a-c]"
ui:TextBoxExtensions.Mask="a5c-5c*9"
Header="Text box with CustomMask in case you want to define your own variable character like a, 9 and *. Mask: a5c-5c*9, 5: [1-5], c: [a-c]"
HeaderTemplate="{StaticResource HeaderTemplate}"
Style="{StaticResource MaskedTextBoxStyle}" />
</StackPanel>
</Grid>
</Page>
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace ExtensionsExperiment.Samples.TextBoxExtensions;
[ToolkitSample(id: nameof(TextBoxMaskSample), "TextBoxMask Extension", description: "A sample for showing how to use the TextBoxMask Extension.")]
public sealed partial class TextBoxMaskSample : Page
{
public TextBoxMaskSample()
{
this.InitializeComponent();
}
}
Surface Dial 支持
SurfaceDialOptions
属性可向数字型 TextBox
添加 Surface Dial 控件中的功能。 它支持通过旋转 Surface Dial(增加或减少值)修改 TextBox
的内容,还可以通过点击 Surface Dial 单击按钮转到下一个焦点元素。 各种选项均通过 SurfaceDialOptions
类型进行设置,该类型在 XAML 中声明,用于从单个位置设置用于给定 TextBox
的所有值。
以下是在 Surface Dial 上滚动 TextBox
时的视觉效果示例:
<Page x:Class="ExtensionsExperiment.Samples.TextBoxExtensions.SurfaceDialOptionsSample"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
mc:Ignorable="d">
<win:TextBox HorizontalAlignment="Left"
VerticalAlignment="Top"
Header="For this sample, you need a Surface Dial"
Text="0">
<ui:TextBoxExtensions.SurfaceDialOptions>
<ui:SurfaceDialOptions EnableHapticFeedback="True"
EnableMinMaxValue="True"
EnableTapToNextControl="False"
Icon="Ruler"
MaxValue="100"
MinValue="0"
RotationResolutionInDegrees="12"
StepValue="1" />
</ui:TextBoxExtensions.SurfaceDialOptions>
</win:TextBox>
</Page>
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace ExtensionsExperiment.Samples.TextBoxExtensions;
[ToolkitSample(id: nameof(SurfaceDialOptionsSample), "SurfaceDialOptions Extension", description: "A sample for showing how to use the SurfaceDialOptions Extension.")]
public sealed partial class SurfaceDialOptionsSample : Page
{
public SurfaceDialOptionsSample()
{
this.InitializeComponent();
}
}
示例
可以在单元测试中查找更多示例。