WPF ItemsControl ItemTemplate Validation - PullRequest
       20

WPF ItemsControl ItemTemplate Validation

1 голос
/ 13 июля 2011

Есть ли способ определить, есть ли у ItemsControl дочерние элементы управления с ошибками проверки?Я хотел бы привязать это значение (логическое значение) к свойству IsEnabled на кнопке.

Ответы [ 2 ]

0 голосов
/ 25 июня 2012

Не знаю, почему ответ Слагтера не сработал для меня (LocalValueEnumerator вернул некоторые свойства, но никогда не связывал их, например, Text).

Мне удалось заставить его работать сэтот код (полученный из этот ответ ):

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);
}
0 голосов
/ 13 июля 2011

Я недавно использовал код из этого предыдущего ответа SO Обнаружение ошибок проверки WPF , чтобы получить именно этот эффект.

У меня есть пользовательский элемент управления, который содержит DataGrid.Usercontrol предоставляет свойство IsValid, которое содержит метод получения, который просто вызывает статическую функцию IsValid, передающую DataGrid как DependencyObject:

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

Свойство IsValid элемента управления может быть затем проверено CanExecuteФункция команды, которую вы привязываете к кнопке, которую вы хотите включить / отключить.

Моя единственная проблема с кодом, на который я ссылался, заключалась в том, что он фактически оценивает проверки на привязках, это означает, что как только вы запуститеесли любое поле, которое является технически недействительным, но еще не было признано недействительным (т. е. пользователь, возможно, еще не ввел никаких данных в это поле, потому что они не дошли до него), теперь будет в недопустимом состоянии - я еще не сделалМы рассмотрели способ избежать или смягчить это.


Редактировать:

Вот обновленная версия, которая не делает недействительными элементы управления, как я упоминал ранее.Я просто закомментировал / немного изменил некоторые строки, но оставил все там, чтобы вы могли увидеть разницу.Обратите внимание, что это также должно выполняться быстрее, так как вы будете выходить, как только найдете первую недействительную привязку.

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