Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF数据绑定异常处理_C#_.net_Wpf_Data Binding - Fatal编程技术网

C# WPF数据绑定异常处理

C# WPF数据绑定异常处理,c#,.net,wpf,data-binding,C#,.net,Wpf,Data Binding,我有一个绑定到Integer属性的文本框。当用户在文本框中输入无法转换为整数(例如名称)的内容时,将引发异常,并且原始属性值不会更改。我想捕获异常,以便禁用连接到该属性的命令?一般来说,如果可能的话,如何从定义属性的视图模型中做到这一点?我最近遇到了同样的问题,我使用了行为来解决它(但如果不需要,您不需要它们,它只是为了在不同的视图中重用我需要的一些代码)。主要思想是在ViewModel中定义一些方法,允许视图通知ViewModel无法检测到的输入错误 因此,首先在ViewModel中定义这些方

我有一个绑定到Integer属性的文本框。当用户在文本框中输入无法转换为整数(例如名称)的内容时,将引发异常,并且原始属性值不会更改。我想捕获异常,以便禁用连接到该属性的命令?一般来说,如果可能的话,如何从定义属性的视图模型中做到这一点?

我最近遇到了同样的问题,我使用了行为来解决它(但如果不需要,您不需要它们,它只是为了在不同的视图中重用我需要的一些代码)。主要思想是在ViewModel中定义一些方法,允许视图通知ViewModel无法检测到的输入错误

因此,首先在ViewModel中定义这些方法。为简单起见,我将只跟踪错误的数量,但您可以存储有关错误的更多信息(如实际错误):

然后,在您的视图中,注册
System.Windows.Controls.Validation.ErrorEvent
,这是一个路由事件,可让您知道组件(以前配置为通知数据错误)何时检测到错误(如异常验证错误):

在命令的CanExecute方法中,您将检查ViewModel的_errorCount字段是否大于0,在这种情况下,应禁用该命令

请注意,您必须将
ValidatesOnExceptions=True,NotifyOnValidationError=True
添加到绑定中,这样才能正常工作。例:

<TextBox Text="{Binding Path=MyProperty, ValidatesOnExceptions=True, NotifyOnValidationError=True}" />
然后,在视图中定义定义IntegerValidationRule的命名空间:

<UserControl 
...
    xmlns:rules="clr-namespace:MyApplication.ValidationRules"
...>

并在绑定中使用规则:

<TextBox>
    <TextBox.Text>
       <Binding Path="MyProperty">
           <Binding.ValidationRules>

              <rules:IntegerValidationRule/>
           </Binding.ValidationRules>
       </Binding>
    </TextBox.Text>
</TextBox>

但无论如何,您需要为每个要验证的非字符串类型创建类,我认为绑定语法现在看起来有点长


问候语

请考虑从视图模型而不是从视图调用命令

private int _myProperty;
public int MyProperty
{
    get
    {
        return _myProperty;
    }
    set
    {
        _myProperty = value;
        // See if the value can be parsed to an int.
        int potentialInt;
        if(int.TryParse(_myProperty, out potentialInt))
        {
            // If it can, execute your command with any needed parameters.
            yourCommand.Execute(_possibleParameter)
        }
    }
}
这将允许您处理用户键入的无法解析为整数的内容, 并且,只有当用户键入的是整数时,才会触发该命令

(我没有测试这段代码,但我认为它可能会有帮助。)

我在网上找到的“最佳”解决方案在

简而言之,验证错误在视图中处理,而不是在ViewModel中处理。您不需要自己的ValidationRule。只需在XAML中为按钮添加样式:

<Button.Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="IsEnabled" Value="false" />
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding ElementName=TextBox1, Path=(Validation.HasError)}" Value="false" />
                            <Condition Binding="{Binding ElementName=TextBox2, Path=(Validation.HasError)}" Value="false" />
                        <Setter Property="IsEnabled" Value="true" />
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>


希望这能帮助那些偶然发现这个问题的人(我知道这么多年后它可能对OP没有帮助)。

谢谢,我喜欢你找到了解决问题的方法,但我现在不会接受这个答案,因为我想看看是否有更简单的解决方案。没问题,我也感兴趣。不管怎样,事情并没有那么复杂:)。很高兴你喜欢它,我认为转换解决方案是最正确的,所以我接受了答案。尽管如此,我还是会在将来进一步探讨这个问题,看看是否能找到一个更健壮的解决方案,它不需要仅仅为了实现一个简单的方法而添加另一个类
if
中,而不是在命令对象中。不要认为OP希望在每个集合中执行该方法。相反,您应该以某种方式禁用该命令。无论如何,这是一个好主意:)我的答案的文字是误导性的。我对它进行了编辑,以更好地反映我的意图。我建议只在需要时从视图模型调用命令,而不是使用绑定。很容易忘记绑定到命令与调用command.Execute()@Riley是一样的,谢谢。我以前没有仔细看过你的答案。但我想告诉你们,我在一篇文章(我不记得了)中读到,你们永远不应该在属性设置器中抛出异常。这可能会造成很多麻烦,尤其是如果该属性是数据绑定的。我接受了您的答案,因为使用字符串是最快的,也是最容易实现的,尽管不是最漂亮的。您是对的,在属性设置器中抛出异常是个坏主意。最好不要生成异常,除非触发异常的条件确实异常。确保使用int.TryParse()而不是int.Parse()。如果传入的内容不是整数,int.TryParse()方法将不会引发异常,因此如果用户键入的内容无法解析为整数,则不必引发任何异常。
<TextBox>
    <TextBox.Text>
       <Binding Path="MyProperty">
           <Binding.ValidationRules>

              <rules:IntegerValidationRule/>
           </Binding.ValidationRules>
       </Binding>
    </TextBox.Text>
</TextBox>
private int _myProperty;
public int MyProperty
{
    get
    {
        return _myProperty;
    }
    set
    {
        _myProperty = value;
        // See if the value can be parsed to an int.
        int potentialInt;
        if(int.TryParse(_myProperty, out potentialInt))
        {
            // If it can, execute your command with any needed parameters.
            yourCommand.Execute(_possibleParameter)
        }
    }
}
<Button.Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="IsEnabled" Value="false" />
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding ElementName=TextBox1, Path=(Validation.HasError)}" Value="false" />
                            <Condition Binding="{Binding ElementName=TextBox2, Path=(Validation.HasError)}" Value="false" />
                        <Setter Property="IsEnabled" Value="true" />
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </Button.Style>