使用 BindingExpression 调用具有 ValidationStep="UpdatedValue" 的 ValidationRule,而不是更新值

2024-04-09

我开始在 WPF 应用程序中使用 ValidationRules,但很困惑。

我有以下简单的规则:

class RequiredRule : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        if (String.IsNullOrWhiteSpace(value as string))
        {
            return new ValidationResult(false, "Must not be empty");
        }
        else
        {
            return new ValidationResult(true, null);
        }

    }
}

在XAML中使用如下:

<TextBox>
    <TextBox.Text>
        <Binding Path="Identity.Name">
            <Binding.ValidationRules>
                <validation:RequiredRule/>
            </Binding.ValidationRules>
         </Binding>
     </TextBox.Text>
</TextBox>

This mostly正如我所期望的那样工作。我很惊讶地发现我的源属性(Identity.Name) 没有被设置;我有一个撤消函数,它永远看不到更改,并且除了重新输入值之外没有其他方法可以恢复该值(不好)。

微软的数据绑定概述 https://msdn.microsoft.com/en-us/library/vstudio/ms752347(v=vs.100).aspx底部描述了验证过程,很好地解释了这种行为。基于此,我想拥有我的ValidationStep set to UpdatedValue.

<validation:RequiredRule ValidationStep="UpdatedValue"/>

这就是事情对我来说变得奇怪的地方。我没有使用作为设置的属性值(即字符串)的对象值来调用 Validate() ,而是得到一个System.Windows.Data.BindingExpression!我在 Microsoft 的文档中没有看到任何描述此行为的内容。

在调试器中,我可以看到源对象(DataContext of the TextBox),导航到该属性的路径,并查看该值已设置。但是,我没有看到任何在验证规则中获取正确属性的好方法。

注:与ValidationStep as ConvertedProposedValue,我得到输入的字符串(我没有使用转换器),但当验证失败时,它也会阻止源属性更新,如预期的那样。和CommittedValue,我得到BindingExpression而不是字符串。

这里有几个问题:

  1. 为什么根据 ValidationStep 设置传递给 Validate() 的参数类型不一致?

  2. 如何从 BindingExpression 获取实际值?

  3. 或者,是否有一种好方法允许用户将 TextBox 恢复到以前的(有效)状态? (正如我提到的,我自己的撤消函数永远不会看到变化。)


我已经解决了从中提取价值的问题BindingExpression,有一个小的限制。

首先,一些更完整的 XAML:

<Window x:Class="ValidationRuleTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ValidationRuleTest"
        Title="MainWindow" Height="100" Width="525">
    <Window.DataContext>
        <local:MainWindowViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="50"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Text="String 1"/>
        <TextBox Grid.Column="1">
            <TextBox.Text>
                <Binding Path="String1" UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <local:RequiredRule ValidationStep="RawProposedValue"/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBlock Text="String 2" Grid.Row="1"/>
        <TextBox Grid.Column="1" Grid.Row="1">
            <TextBox.Text>
                <Binding Path="String2" UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <local:RequiredRule ValidationStep="UpdatedValue"/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
    </Grid>
</Window>

请注意,第一个 TextBox 使用ValidationStep="RawProposedValue"(默认),而第二个使用ValidationStep="UpdatedValue",但两者都使用相同的验证规则。

一个简单的 ViewModel(忽略 INPC 和其他有用的东西):

class MainWindowViewModel
{
    public string String1
    { get; set; }

    public string String2
    { get; set; }
}

最后,新的RequiredRule:

class RequiredRule : ValidationRule
{
    public override ValidationResult Validate(object value,
        System.Globalization.CultureInfo cultureInfo)
    {
        // Get and convert the value
        string stringValue = GetBoundValue(value) as string;

        // Specific ValidationRule implementation...
        if (String.IsNullOrWhiteSpace(stringValue))
        {
            return new ValidationResult(false, "Must not be empty"); 
        }
        else
        {
            return new ValidationResult(true, null); 
        }
    }

    private object GetBoundValue(object value)
    {
        if (value is BindingExpression)
        {
            // ValidationStep was UpdatedValue or CommittedValue (Validate after setting)
            // Need to pull the value out of the BindingExpression.
            BindingExpression binding = (BindingExpression)value;

            // Get the bound object and name of the property
            object dataItem = binding.DataItem;
            string propertyName = binding.ParentBinding.Path.Path;

            // Extract the value of the property.
            object propertyValue = dataItem.GetType().GetProperty(propertyName).GetValue(dataItem, null);

            // This is what we want.
            return propertyValue;
        }
        else
        {
            // ValidationStep was RawProposedValue or ConvertedProposedValue
            // The argument is already what we want!
            return value;
        }
    }
}

The GetBoundValue()如果它获得 BindingExpression,方法将挖掘出我关心的值,或者如果不是,则简单地回退参数。真正的关键是找到“路径”,然后使用它来获取属性及其值。

限制:在我原来的问题中,我的绑定有Path="Identity.Name",当我深入研究 ViewModel 的子对象时。这会not有效,因为上面的代码期望路径直接指向绑定对象上的属性。幸运的是,我已经展平了 ViewModel,因此情况不再如此,但解决方法可能是首先将控件的数据上下文设置为子对象。

我想对 Eduardo Brites 给予一些信任,因为他的回答和讨论让我重新开始深入研究这个问题,并且确实为他的难题提供了一部分。另外,虽然我打算完全放弃 ValidationRules 并使用 IDataErrorInfo 代替,但我喜欢他关于将它们一起用于不同类型和复杂性验证的建议。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 BindingExpression 调用具有 ValidationStep="UpdatedValue" 的 ValidationRule,而不是更新值 的相关文章

  • WPF 在菜单上选择项目或在视图模型中获取命令参数

    我正在寻找几个小时来解决一个简单的问题 我想在我的菜单项上使用 SelectedItem 但经过几个小时的 stackoverflow 我发现这是不可能的 我发现了很多关于 CommandParameter 的信息 但我不明白它是如何工作的
  • 验证属性被触发两次

    在我的 MVC3 应用程序中 我有模型 未删除重要属性 public class AccountViewModel StringLength 65 public string Property1 get set StringLength 6
  • 如何更改 WPF TabControl 的 ItemTemplate 的样式以便设置选项卡标题的背景颜色?

    我使用 WPF TabControl 的 ItemTemplate 属性来绑定每个 TabItem 标头的内容 我还使用 ItemContainerStyle 属性将 TabItem 的内容设置为动态选择的用户控件 此方法 100 按预期工
  • WPF:将布尔值显示为“是”/“否”

    我有一个布尔值 需要在 TextBlock 中显示为 是 或 否 我尝试使用 StringFormat 执行此操作 但我的 StringFormat 被忽略并且 TextBlock 显示 True 或 False
  • 使用路径=。和绑定内的转换器

    我无法为 TreeViewItems 定义触发器 我相信这只是一些语法问题 但我不知道还要写什么 这是触发器
  • 我的 C# .NET 团队是否应该迁移到 Windows Presentation Foundation? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在 CAST/CONVERT 之前检查 VARCHAR(n) 的 XML 格式是否正确

    我的公司有一个日志表 其中包含VARCHAR N 放置字符串的列 即supposed是 XML 但事实证明它并不总是格式良好的 为了对日志记录进行分析 以确定错误趋势等 我一直在使用LIKE陈述 然而 这非常慢 最近 我发现SQL Serv
  • 在 MVVM 中,可以在视图后面的代码中访问 ViewModel 吗?

    在 MVVM 模式中 是否可以接受甚至可以访问视图代码后面的 ViewModel 属性 我有一个可观察的集合 它填充在 ViewModel 中 我需要在视图中使用它来绑定到带有链接列表的无限滚动条 IE private LinkedList
  • Spring验证非空元素的字符串列表

    我有一个模型类 其中包含字符串列表 该列表可以为空 也可以包含元素 如果它有元素 这些元素不能为空 举个例子 假设我有一个名为 QuestionPaper 的类 它有一个 QuestionId 列表 其中每个都是一个字符串 class Qu
  • wpf工具包折线图,无点且具有不同的线条颜色

    我有一些图表 我想动态添加没有数据点的 LineSeries 只是带有一些自定义颜色的线条 我发现隐藏数据点的唯一方法是 Style style new Style typeof LineDataPoint style Setters Ad
  • CakePHP 中没有模型的简单表单

    我正在尝试在产品页面中添加请求附加信息的表单 这是一个简单的表格 包含姓名 国家 地区 电子邮件和问题字段 我创立了这个tutorial http snook ca archives cakephp contact form cakephp
  • 验证 C# 中的属性

    让我们建议我有一个接口并从中继承类 internal interface IPersonInfo String FirstName get set String LastName get set internal interface IRe
  • 为什么在此 MultiBinding 上未调用 ConvertBack?

    我的组合框列表联系人使用 MultiBinding 绑定到 FullName 和 PhoneExtension IMul tiValueConverter 的 Convert 方法被调用 但 ConvertBack 未被调用 为什么 组合框
  • 如何检查用户电子邮件的唯一性并将结果传递给 jQuery?

    我有这个问题 我正在控制器中检查用户电子邮件并发送 json 成功响应 如果已获取 并添加输入的 css 样式 我还需要阻止提交并添加一些消息 这是我的检查电子邮件操作 使用本文 http paydrotalks com posts 45
  • WPF ListBoxItem 双击?

    WPF ListBox 没有 DoubleClick 事件 至少据我所知没有 是否有针对此问题的解决方法 让我双击某个项目即可让事件处理程序对其执行某些操作 感谢您的帮助 可以将带有参数的命令绑定到ListBoxItem不使用代码隐藏 or
  • 具有多个验证组的 Page_ClientValidate() - 如何同时显示多个摘要?

    ASP NET 2 0 假设我有两个验证组 valGrpOne 和 valGrpTwo 以及两个验证摘要 valSummOne 和 valSummTwo 分解部分的原因纯粹是为了美观 一个提交按钮会触发对两组的验证 现在我想触发客户端验证
  • 根据 AD 组成员身份限制对 WPF 视图的访问

    我们有一个 WPF 应用程序 我们希望根据用户的 AD 组成员身份限制对应用程序的访问 我们可以将其作为每个视图的属性 或者作为用户启动应用程序时的检查吗 任何代码示例将不胜感激 在 NET 3 5 及更高版本上执行此操作的最简单方法是使用
  • 将属性值指定为 CDATA

    可以将 XML 属性值指定为 CDATA 吗 如果是的话 相同的模式是什么 如果不是 为什么 XML 中没有解决这个限制 不 你不能这样做 在什么构成属性和什么构成子元素之间存在非常细的界限 并且存在很大的争论 看here https st
  • 全屏模式下的 XBAP

    我想以全屏模式运行 XBAP 有没有办法让IE全屏打开XBAP 由于我以完全信任的方式运行 每当用户单击全屏按钮时 我都会使用 Process Start 方法以 kiosk 模式打开 IE 以下代码解决了我的问题 Process Star
  • http://jigsaw.w3.org/css-validator/ 和 http://www.css-validator.org/ CSS 验证器之间的区别?

    我尝试使用两个验证器验证我的 CSS 但它们给出了不同的结果 http www css validator org http www css validator org 返回的错误 在我的例子中为 245 比http jigsaw w3 o

随机推荐