如何在WPF中关闭默认验证?

nfs0ujit  于 2023-06-07  发布在  其他
关注(0)|答案(3)|浏览(193)

WPF似乎有一些默认打开的验证规则。当我在绑定文本框中输入非数字文本并按Tab键退出时,它周围会显示一个读取边框。这是怎么回事?我已经将ValidatesOnExceptions设置为false,验证规则从何而来?我使用的是.Net framework 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();
        }
    }
}
kkbh8khc

kkbh8khc1#

你不能 neverint属性设置为有效的int值以外的任何值。
这种“验证”,或者更确切地说,编程语言的类型安全特性,不能被关闭。
但是,如果您愿意,您可以摆脱或自定义默认错误 template。只需将Validation.ErrorTemplate属性设置为emoty 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>
bihw5rsg

bihw5rsg2#

在应用启动时,您可以将此调用添加到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属性的十进制值更加容易。

yi0zb3m4

yi0zb3m43#

扩展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;
        }
    }
}

相关问题