WPF 数据表格验证 Bug?

8
这可能是预期的功能,但对我来说似乎是一个错误。
我正在使用开箱即用的WPF DataGrid,绑定到ObservableCollection并尝试使用一些验证规则以提供良好的用户反馈。不用说,有比我数得出的问题更多,但我会坚持立即解决问题。
以下是问题的摘要:
1.将ItemsSource属性绑定到ObservableCollection 2.填充集合 3.以会导致验证错误的方式编辑网格中的项目 4.从ObservableCollection中以编程方式删除该项
当执行这些步骤时,GridView正确地识别到已从集合中删除该项,并从网格中删除了该行。然而,Grid现在被卡在无效状态中,并且无法通过UI在Grid上执行进一步操作!
再次强调,这对我来说似乎是一个相当大的错误,因为能够以编程方式从集合中删除项目是一件大事。
有人遇到过这种情况吗?有什么建议可以解决它吗?
值得注意的是,我创建了一个单独的解决方案来隔离此问题,但是为了回答您可能有的一些问题:
您的对象是否实现了INotifyPropertyChanged?是的
这是自定义集合吗?不是,只是普通的ObservableCollection 您如何从集合中删除项目?
//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
@SuperOli - 删除操作发生在保存操作期间。数据访问是2层的,因此从网格中“删除”项目实际上意味着将其标记为删除。编辑是批处理的,包括已删除的项目,并在保存事件期间发送到服务器。当我从服务器获取项目列表时,我必须在客户端检查哪些操作成功,失败等... 成功的删除操作意味着我可以从底层集合中删除该项。但是,我已经创建了一个简单的解决方案来独立测试这个问题,并获得了相同的结果。 - Josh
愚蠢的问题...你是先修复验证错误还是删除?因为在我创建的应用程序中,我的单元格会一直停留在“编辑模式”直到我取消更改(ESC)或输入有效字符串。另一件你可能想要尝试的事情是从 Codeplex(http://wpf.codeplex.com/)下载DataGrid源代码并引用它。也许那样,你就能调试DataGrid状态了。 - SuperOli
不,验证错误在移除之前并没有被修复,这是问题的根源。当移除与某一行绑定的底层对象时,如果该行存在验证错误,则即使该行在视觉上已被移除,DataGrid仍处于无效状态。 - Josh
调试了一下,发现在删除行后,私有属性DataGrid.HasCellValidationError仍然保持“true”。只有在提交编辑时(更确切地说,在DataGrid.OnExecutedCommitEdit()中)才会设置它。当此属性为true时,它会阻止进入“编辑模式”。我认为这看起来像是一个错误,应该向Microsoft报告。我猜你想找到一个解决方法? - SuperOli
显示剩余2条评论
3个回答

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);
    }
}

1
我花了几个小时试图找出问题所在。最后,对项目进行简单的刷新解决了问题。希望这可以帮到你。
YourDataGrid.Items.Refresh();

你会把这个刷新放在哪里? - l33t

0

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

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

为此,我们创建了一个单元格模板,其中包含一个红色框架,该框架与数据触发器绑定,每当给定属性的错误状态更改时就会调用该触发器。 实际创建datatrigger的是一个依赖属性,它接收ViewModel属性的绑定路径并创建绑定。

i.e:

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接