WPF ItemsControl ItemTemplate验证

时间:2011-07-13 00:23:02

标签: wpf validation data-binding itemscontrol

有没有办法确定ItemsControl是否有任何带有验证错误的子控件?我想将此值(布尔值)绑定到Button上的IsEnabled属性。

2 个答案:

答案 0 :(得分:0)

我最近使用了之前的SO回答 Detecting WPF Validation Errors 中的代码,这对此非常有效。

我有一个包含DataGrid的用户控件。 usercontrol公开一个包含getter的IsValid属性,它只是调用静态IsValid函数作为DependencyObject传入DataGrid:

public class MyControl : UserControl
{
    public bool IsValid
    {
        get { return Validator.IsValid(MyDataGrid); }
    }
}

然后可以通过绑定到要启用/禁用的按钮的命令的CanExecute函数来检查控件的IsValid属性。

我链接的代码的唯一问题是它实际上评估了绑定的验证,这意味着只要你运行任何技术上无效但尚未失效的字段(即用户可能尚未输入该字段中的任何数据,因为他们没有得到它)​​现在将处于无效状态 - 我还没有找到避免或减轻这种情况的方法。


修改

这是一个更新版本,不会像我之前提到的那样使控件无效。我只是评论出来/略微改变了一些线条,但是把所有东西留在那里,这样你就能看出差异。请注意,这也应该更快,因为您将在找到第一个无效绑定时退出。

public static bool IsValid(DependencyObject parent)
{
    // Validate all the bindings on the parent
    bool valid = true;
    LocalValueEnumerator localValues = parent.GetLocalValueEnumerator();
    while (localValues.MoveNext())
    {
        LocalValueEntry entry = localValues.Current;
        if (BindingOperations.IsDataBound(parent, entry.Property))
        {
            Binding binding = BindingOperations.GetBinding(parent, entry.Property);
            foreach (ValidationRule rule in binding.ValidationRules)
            {
                ValidationResult result = rule.Validate(parent.GetValue(entry.Property), null);
                if (!result.IsValid)
                {
                    //BindingExpression expression = BindingOperations.GetBindingExpression(parent, entry.Property);
                    //System.Windows.Controls.Validation.MarkInvalid(expression, new ValidationError(rule, expression, result.ErrorContent, null));
                    //valid = false;
                    return false;
                }
            }
        }
    }

    // Validate all the bindings on the children
    for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i)
    {
        DependencyObject child = VisualTreeHelper.GetChild(parent, i);
        if (!IsValid(child))
        {
            //valid = false;
            return false;
        }
    }

    //return valid;
    return true;
}

答案 1 :(得分:0)

我不知道为什么,slugter的答案对我不起作用(LocalValueEnumerator返回了一些属性但从来没有绑定过,如Text)。

我设法让它使用此代码(源自this answer):

public static bool IsValid(DependencyObject obj)
{
    // The dependency object is valid if it has no errors, 
    //and all of its children (that are dependency objects) are error-free.
    return !Validation.GetHasError(obj) &&
        GetVisualTreeChildren(obj)
        .OfType<DependencyObject>()
        .All(child => IsValid(child));
}

//VisualTreeHelper don't have a method to get all the children of a visual object
private static IEnumerable GetVisualTreeChildren(DependencyObject parent)
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
        yield return VisualTreeHelper.GetChild(parent, i);
}