WPF 似乎有一些默认打开的验证规则。当我在绑定文本框中输入非数字文本并用 Tab 键将其移出时,它周围会显示一个读取边框。这里发生了什么?我已将 ValidatesOnExceptions 设置为 false,验证规则来自哪里?我正在使用 .Net 框架 4.5.2 版本。
这是我的 XAML
<Window x:Class="WpfApplication2.MainWindow"
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:local="clr-namespace:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="159.206" Width="193.953">
<Grid>
<TextBox x:Name="textBox" Height="23" HorizontalAlignment="Left" VerticalAlignment="Top" TextWrapping="Wrap"
Text="{Binding Foo, ValidatesOnExceptions=False, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
Width="91" Margin="10,10,0,0"/>
<TextBox x:Name="textBox1" HorizontalAlignment="Left" Height="23" Margin="10,48,0,0"
TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="91"/>
</Grid>
</Window>
这是背后的代码
namespace WpfApplication2
{
public partial class MainWindow : Window
{
public int Foo { get; set; } = 42;
public MainWindow()
{
InitializeComponent();
}
}
}
您可以从不将
int
属性设置为除有效 int
值以外的任何值。
这种“验证”,或者更确切地说,编程语言的类型安全功能,无法关闭。
但是,如果您愿意,您可以删除或自定义默认错误模板。只需将
Validation.ErrorTemplate
属性设置为表情 ControlTemplate
:
<TextBox x:Name="textBox" Height="23" HorizontalAlignment="Left" VerticalAlignment="Top" TextWrapping="Wrap"
Text="{Binding Foo, ValidatesOnExceptions=False, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
Width="91" Margin="10,10,0,0">
<Validation.ErrorTemplate>
<ControlTemplate />
</Validation.ErrorTemplate>
</TextBox>
在应用程序启动时,您可以将此调用添加到 FrameworkCompatibiltyPreferences 以禁止所有文本框干扰您的输入:
class App
{
[STAThread]
public static void Main(params string[] args)
{
System.Windows.FrameworkCompatibilityPreferences.KeepTextBoxDisplaySynchronizedWithTextProperty = false;
Application app = new Application();
app.Run(new Window1());
}
}
如果您使用数据绑定,文本框似乎仍会防止无效输入。将显示验证错误(默认为红色边框),并且视图模型属性不会设置为无效值。但现在您可以输入任何您想要的字符串。使输入绑定到 float 或 double 属性的十进制值变得更加容易。
扩展 mm8 的出色答案,对于任何希望为可空
int
执行此操作的人,您可以执行以下操作;
XAML
<Window.Resources>
<ResourceDictionary>
<converters:NullableIntToStringConverter x:Key="NullableIntConverter" />
</ResourceDictionary>
</Window.Resources>
<!-- ...snip ... -->
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" Margin="5"
Text="{Binding Path=SearchRackNumber,Mode=TwoWay,Converter={StaticResource NullableIntConverter},ValidatesOnExceptions=False}"
PreviewTextInput="TxtRackNumber_OnPreviewTextInput"
PreviewKeyDown="TxtRackNumber_OnPreviewKeyDown">
<Validation.ErrorTemplate>
<ControlTemplate />
</Validation.ErrorTemplate>
</TextBox>
代码背后
此处的事件阻止用户输入非数字字符。就我而言,我只关心正整数值。需要两个事件来处理大多数文本,以及单独的空格(请参阅here了解原因)。
private void TxtRackNumber_OnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
var numericRegEx = new Regex("^[0-9]{0,10}$");
e.Handled = !numericRegex.IsMatch(e.Text);
}
private void TxtRackNumber_OnPreviewKeyDown(object sender, KeyEventArgs e)
{
// a separate event is needed to handle the space as it doesn't trigger the
// OnPreviewTextInput event. This is by WPF design to handle IME languages
// (ones that take more than one key press to enter a character, e.g., Chinese).
e.Handled = e.Key == Key.Space;
}
转换器
using System;
using System.Globalization;
using System.Windows.Data;
namespace YourApp
{
internal class NullableIntToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null) return null;
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null || string.IsNullOrWhiteSpace(value.ToString())) return null;
var stringValue = value.ToString();
if (!int.TryParse(stringValue, out int parsed)) return null;
return parsed;
}
}
}
我一直在寻找一个更简单的解决方案,代码最少,并且可以在样式中使用,这也有效:
XAML
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>