【问题标题】:WPF DataGrid Validation Bug?WPF DataGrid 验证错误?
【发布时间】:2011-06-29 09:02:19
【问题描述】:

这可能是预期的功能,但对我来说确实是一个错误。

我正在使用开箱即用的 WPF DataGrid,绑定到 ObservableCollection 并尝试 使用一些验证规则以提供良好的用户反馈。不用说,问题多得我数不过来,但我会坚持立即处理。

问题总结如下:

  1. ItemsSource 属性绑定到ObservableCollection<T>
  2. 填充集合
  3. 以会导致验证错误的方式编辑网格中的项目
  4. 以编程方式从ObservableCollection<T> 中删除该项目

执行这些步骤后,GridView 会正确识别该项目已从集合中删除,并从网格中删除该行。但是,Grid 现在卡在无效状态,无法通过 Grid 上的 UI 执行进一步的操作!

再次,这对我来说似乎是一个重大错误,因为能够以编程方式从集合中删除项目是一件大事。

有人遇到过这个吗?有关如何解决它的任何建议?

值得注意的是,我创建了一个单独的解决方案来隔离这个问题,但要回答您可能有的一些问题:

你的对象是否实现了INotifyPropertyChanged

这是一个自定义集合吗? 不是普通的旧 ObservableCollection<T>

你是如何从你的收藏中删除物品的?

//Find any newly added item and remove it  
var someObject = SomeObjects
             .Where(obj => obj.SomeProperty == SomeValue)
             .First();

SomeObjects.Remove(someObject );

你是如何绑定你的验证规则的?

<DataGridTextColumn Header="SomeProperty">
    <DataGridTextColumn.Binding>
        <Binding Path="SomeProperty">
            <Binding.ValidationRules>
                <val:RequiredValidator ValidationStep="ConvertedProposedValue" 
                     ValidatesOnTargetUpdated="True" />
            </Binding.ValidationRules>
        </Binding>
    </DataGridTextColumn.Binding>
</DataGridTextColumn>

你的验证规则是什么样的?

public class RequiredValidator : ValidationRule
{
    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        if (value == null || String.IsNullOrWhiteSpace(value as String))
            return new ValidationResult(false, "Field is required!");

        return ValidationResult.ValidResult;
    }
}

【问题讨论】:

  • 我对您确切在何时何地进行移除感兴趣。
  • @SuperOli - 删除发生在保存操作期间。数据访问是 2 层,因此从网格中“删除”一个项目实际上意味着将其标记为删除。编辑是批处理的,包括已删除的项目,并在保存事件期间发送到服务器。当我从服务器取回项目列表时,我必须检查客户端以查看哪些操作成功、失败等......成功的删除操作意味着我可以从基础集合中删除项目。但是,我创建了一个简单的解决方案来独立测试,结果相同。
  • 愚蠢的问题...您在删除之前修复了验证错误吗?因为在我为在此处重现您的错误而创建的应用程序中,我的单元格一直处于“编辑模式”,直到我取消更改 (ESC) 或输入有效字符串。您可能想尝试的另一件事是从 Codeplex (wpf.codeplex.com) 下载 DataGrid 源代码并参考此代码。也许这样,您就可以调试 DataGrid 状态。
  • 不,验证错误在删除之前没有修复,这是问题的根源问题。删除绑定行的底层对象时,如果该行存在验证错误,则即使该行已被视觉删除,DataGrid 仍处于无效状态。
  • 调试了一下,发现私有属性 DataGrid.HasCellValidationError 在删除行后仍然为“真”。它仅在提交版本时设置(更准确地说是在 DataGrid.OnExecutedCommitEdit() 中)。当此属性为真时,它会阻止进入“编辑模式”。在我看来,它看起来像一个错误,应该向 Microsoft 报告。我猜你想找到一个解决方法?

标签: c# .net wpf validation gridview


【解决方案1】:

我遇到了同样的问题,经过漫长的搜索过程,我找到了解决方案:

您可以创建一个派生自 DataGrid 的类。在那里,您可以通过反射访问私有属性。如果您现在删除了一个无效项,您可以调用函数 SetGridWritable() 并且其他值可以再次编辑。

public class MyDataGrid : DataGrid
{
    public void SetGridWritable()
    {
        BindingFlags bindingFlags = BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Instance;
        PropertyInfo cellErrorInfo = this.GetType().BaseType.GetProperty("HasCellValidationError", bindingFlags);
        PropertyInfo rowErrorInfo = this.GetType().BaseType.GetProperty("HasRowValidationError", bindingFlags);
        cellErrorInfo.SetValue(this, false, null);
        rowErrorInfo.SetValue(this, false, null);
    }
}

【讨论】:

    【解决方案2】:

    我花了几个小时试图找出发生了什么。最后,对 Items 进行简单的刷新就解决了这个问题。希望这会有所帮助。

    YourDataGrid.Items.Refresh();
    

    【讨论】:

    • 你会把这个刷新放在哪里?!
    【解决方案3】:

    如果您有兴趣,我有一个非解决方案:

    我们发现整个验证机制充满了不受欢迎的行为。 例如 - 我们希望允许我们的用户输入无效数据,并且只标记错误。

    为此,我们创建了一个带有红框的单元格模板,该模板与一个数据触发器绑定,只要给定属性的错误状态发生变化,就会调用该触发器。 数据触发器的实际创建是由一个依赖属性完成的,该属性接收到 ViewModel 属性的绑定路径并创建绑定

    即:

    DataTrigger errorTrigger = CreateTrigger(CreateDirectBinding(property,new HasErrorValueConverter()), CreateErrorSetter(property));
    

    这可以解决与验证错误相关的问题。

    【讨论】:

      猜你喜欢
      • 2011-07-03
      • 1970-01-01
      • 1970-01-01
      • 2014-08-08
      • 1970-01-01
      • 2012-12-09
      • 2015-10-04
      • 2018-09-06
      • 2011-09-29
      相关资源
      最近更新 更多