C# 未为textbox value>int.MaxValue调用绑定属性

C# 未为textbox value>int.MaxValue调用绑定属性,c#,wpf,xaml,C#,Wpf,Xaml,未为textbox value>int.MaxValue调用绑定属性 如果输入的值大于int.MaxValue,我需要恢复到文本框中的最后一个值。 请参阅下面的代码 MainWindow.xaml <Window x:Class="SampleWPFApplication.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://

未为textbox value>int.MaxValue调用绑定属性

如果输入的值大于int.MaxValue,我需要恢复到文本框中的最后一个值。 请参阅下面的代码

MainWindow.xaml

<Window x:Class="SampleWPFApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBox Text="{Binding Count, UpdateSourceTrigger=LostFocus}" />
        <Button Content="Click!" Width="100" Height="50"/>
    </StackPanel>
</Window>
MainWindow.xaml.cs

using System.Windows;
namespace SampleWPFApplication
{
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
             this.DataContext = this;
         }

         private int _count = 32;
     public int Count
         {
            get { return _count;}
            set 
            {
                if(value <= int.MaxValue)
                    _count = value;
            }
         }
     }
}
在Count属性的setter处设置断点。对于小于int.MaxValue的值,将命中此断点。 在我的系统上,int.Maxvalue的值为2147483647。若您给出的值大于此值,那个么断点将不会命中,文本框将被红色矩形包围。 对于超出范围的值,我希望恢复到文本框中的上一个值

如果我将上述属性设置器中的int.MaxValue替换为不等于int.MaxValueFor(例如999)的值,则它可以正常工作。 我相信textbox内部有一个最大值int.MaxValue,当给出一个大于这个值的值时,它会进行自己的验证,验证失败,绑定也不会更新

我已在xaml中将PresentationTraceSources.TraceLevel=设置为高,如链接中所述 得到了StackOverFlowException

System.Windows.Data警告:95:BindingExpression哈希=52085517: 已从TextBox hash=10223660 System.Windows.Data获取LostFocus事件 警告:90:BindingExpression散列=52085517:Update-获取原始数据 值“2147483649”SampleWPFApplication.vshost.exe“托管” v4.0.30319:已加载 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\PresentationFramework SystemData\v4.0_4.0.0.0_uuB77A5C561934E089\PresentationFramework SystemData.dll', 已跳过加载符号。模块已优化,调试器选项 “仅我的代码”已启用。System.Windows.Data错误:7:ConvertBack 无法将值“2147483649”转换为“字符串”。 BindingExpression:Path=Count;DataItem='MainWindow'名称=;目标 元素为“TextBox”Name=;目标属性为“文本”类型 'String'OverflowException:'System.OverflowException:值为 对于Int32来说太大或太小。在 System.Number.ParseInt32String s,NumberStyles样式, NumberFormatInfo信息位于 System.String.System.IConvertible.ToInt32IFormatProvider提供程序 在System.Convert.ChangeTypeObject值处,键入conversionType, IFormatProvider提供程序位于 MS.Internal.Data.SystemConvertConverter.ConvertBack对象o,类型 类型,对象参数,CultureInfo区域性位于 System.Windows.Data.BindingExpression.ConvertBackHelperIValueConverter 转换器、对象值、类型sourceType、对象参数、, CultureInfo区域性'System.Windows.Data警告:93: BindingExpression哈希=52085517:更新-隐式转换器 生成了{DependencyProperty.UnsetValue}System.Windows.Data警告: 94:BindingExpression哈希=52085517:Update-使用最终值 {DependencyProperty.UnsetValue}

有人能解释一下这种行为和克服它的方法吗。? 还有,有没有办法覆盖红色矩形的行为

类似的问题没有解决办法


解决方法:一种解决方法是将属性的数据类型从int更改为long。

无法访问Setter的原因是WPF的自动绑定验证过程已停止IsValid=false,这是作为整数所需的值,不能大于int.MaxValue。它基本上已经预先询问了setter的要求,然后在失败时显示了ErrorTemplate

您可以更改ErrorTemplate。这会在文本框周围放置一个橙色边框,并显示报告的错误消息

<TextBox Text="{Binding Count, UpdateSourceTrigger=LostFocus}">
        <Validation.ErrorTemplate>
            <ControlTemplate>
                <StackPanel>
                    <!-- Placeholder for the TextBox itself -->
                    <Border BorderBrush="Orange" BorderThickness="2">
                        <AdornedElementPlaceholder x:Name="textBox"/>
                    </Border>
                    <TextBlock Text="{Binding [0].ErrorContent}" Foreground="Green"/>
                </StackPanel>
            </ControlTemplate>
        </Validation.ErrorTemplate>
      </TextBox>

是一篇关于这种行为的非常好的文章

为什么不调用setter是因为在设置属性之前,值首先由绑定转换为适当的类型。在本例中,字符串转换为int。由于2147483649不是有效的int值,它大于int.MaxValue,因此转换失败,绑定中止源更新。在这种情况下,正如@dellywheel在其回答中提到的那样,绑定的IsValid属性被设置为false,错误模板显示在文本框中

实现所述行为的一种方法是定义一个代理属性,该属性负责验证/转换并绑定到它,而不是Count属性。下面是一个例子:

public string CountProxy
{
    get { return Count.ToString(); }
    set
    {
        int n;
        if (int.TryParse(value, out n) && n <= MaxValue)
            Count = n;
    }
}

如果MaxValue将是int.MaxValue,您可以跳过比较,因为int.TryParse将为所有超出范围的值返回false。

感谢Grx70和dellywheel提供的解决方法。然而,它不满足我的要求。要求只允许数字,对于文本框中输入或粘贴的任何超出范围的值,恢复为以前的值。另一个问题是文本框中的LostFocus值为空。它显示红色矩形。我不想在出错时显示任何矩形,但要恢复到以前的值。如果属性的数据类型从int/long更改为String,则一切都可以正常工作。所有值都会命中setter,我们可以将验证放在属性中,并根据验证结果对其进行更改。但是,我不喜欢将“Count”属性设置为字符串,而将其设置为数字和mig 对于展望未来的人来说,他赋予了不同的含义。