WPF验证:清除所有验证错误

我有一个WPF UserControl与其中的许多其他控件。 TextBoxes就是其中之一。 每个TextBox都有自己的验证:

<TextBox>
    <TextBox.Text>
        <Binding Path="MyPath" StringFormat="{}{0:N}" NotifyOnValidationError="True">
            <Binding.ValidationRules>
                <r:MyValidationRule ValidationType="decimal" />
            </Binding.ValidationRules>
        </Binding>
    <TextBox.Text>
<TextBox>

一个

现在假设用户输入一些无效字符。 他们都会变得突出红色。

现在我想重置所有验证错误 (来自不正确的输入)并设置来自DataContext 的最近正确值

我在构造函数中设置了DataContext,我不想改变它(DataContext = null当时不会帮助我):

DataContext = _myDataContext = new MyDataContext(..);

我已经找到了这些类:

Validation.ClearInvalid(..)
BindingExpression.UpdateTarget();

我认为这些类可以帮助我,但是他们需要Binding一个具体的FrameworkElement ,我想为它们全局进行。

我应该反复通过Visual Tree(这真的是我不喜欢的)还是有更好的解决方案呢?


这就是BindingGroup的用途......你可以在所有控件的容器上设置一个BindingGroup,例如包含它们的面板。 这会导致DataContext的更新被保留,直到您调用BindingGroup上的UpdateSources。 如果你想重置用户的输入,你可以调用CancelEdit,而BindingGroup会将容器内的所有控件重置为DataContext的(仍未改变的)值。


为什么你不会为数据源的所有属性触发NotifyPropertyChanged? 这将更新绑定和UI控件应该从datacontext获取值(这是有效的,因此验证错误将被清除)?


我有同样的问题。 多个经过验证的页面上的控件。 我发现/使这个解决方案更新(并清除所有的验证)DependencyObject的子域:

using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;

/// <summary>
/// Updates all binding targets where the data item is of the specified type.
/// </summary>
/// <param name="root">The root.</param>
/// <param name="depth">The depth.</param>
/// <param name="dataItemType">Type of the data item.</param>
/// <param name="clearInvalid">Clear validation errors from binding.</param>
public static void UpdateAllBindingTargets(this DependencyObject root, int depth, Type dataItemType, bool clearInvalid)
{
    var bindingExpressions = EnumerateDescendentsBindingExpressions(root, depth);
    foreach (BindingExpression be in bindingExpressions.Where(be => be.DataItem != null && be.DataItem.GetType() == dataItemType))
    {
        if (be != null)
        {
            be.UpdateTarget();
            if (clearInvalid)
                System.Windows.Controls.Validation.ClearInvalid(be);
        }
    }
}

/// <summary>
/// Enumerates all binding expressions on descendents.
/// </summary>
/// <param name="root">The root.</param>
/// <param name="depth">The depth.</param>
/// <returns></returns>
public static IEnumerable<BindingExpression> EnumerateDescendentsBindingExpressions(this DependencyObject root, int depth)
{
    return root.EnumerateDescendents(depth).SelectMany(obj => obj.EnumerateBindingExpressions());
}

/// <summary>
/// Enumerates the descendents of the specified root to the specified depth.
/// </summary>
/// <param name="root">The root.</param>
/// <param name="depth">The depth.</param>
public static IEnumerable<DependencyObject> EnumerateDescendents(this DependencyObject root, int depth)
{
    int count = VisualTreeHelper.GetChildrenCount(root);
    for (int i = 0; i < count; i++)
    {
        var child = VisualTreeHelper.GetChild(root, i);
        yield return child;
        if (depth > 0)
        {
            foreach (var descendent in EnumerateDescendents(child, --depth))
                yield return descendent;
        }
    }
}

/// <summary>
/// Enumerates the binding expressions of a Dependency Object.
/// </summary>
/// <param name="element">The parent element.</param>
public static IEnumerable<BindingExpression> EnumerateBindingExpressions(this DependencyObject element)
{
    if (element == null)
    {
        throw new ArgumentNullException("element");
    }

    LocalValueEnumerator lve = element.GetLocalValueEnumerator();

    while (lve.MoveNext())
    {
        LocalValueEntry entry = lve.Current;

        if (BindingOperations.IsDataBound(element, entry.Property))
        {
            if (entry.Value is PriorityBindingExpression)
            {
                foreach (BindingExpression expr in ((PriorityBindingExpression)entry.Value).BindingExpressions)
                    yield return expr;
            }
            else if (entry.Value is MultiBindingExpression)
            {
                foreach (BindingExpression expr in ((MultiBindingExpression)entry.Value).BindingExpressions)
                    yield return expr;
            }
            else
                yield return entry.Value as BindingExpression;
        }
    }
}
链接地址: http://www.djcxy.com/p/46615.html

上一篇: WPF Validation: Clearing all validation errors

下一篇: How to set PlatformToolset from custom property sheet in Visual Studio 2010