首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >INotifyDataErrorInfo仅在需要时触发

INotifyDataErrorInfo仅在需要时触发
EN

Stack Overflow用户
提问于 2018-01-29 18:48:00
回答 1查看 315关注 0票数 1

我已经在我的模型上实现了INotifyDataErrorInfo。但我似乎不能在需要的时候使用它。例如。它不应该在启动时或在我键入时验证错误。仅当单击按钮(保存)时。

我目前在我的XAML中有这个:

代码语言:javascript
运行
复制
<TextBox Text="{Binding Car.Model, ValidatesOnNotifyDataErrors=False, UpdateSourceTrigger=Explicit}"/>

在SaveCommand下的我的ViewModel中:

代码语言:javascript
运行
复制
Car.Validate();
if (Car.HasErrors)
{
 return;
}
//else save 

我的模型看起来像这样:

代码语言:javascript
运行
复制
 Public class Car:ValidateModelBase
 {
    private string _model;
    [Required (ErrorMessage ="This field is required")]
    public string Model
    {
        get { return _model; }
        set { _model= value; RaisePropertyChanged(); }
    }
 }

然后是我的ValidateModelBase实现:

代码语言:javascript
运行
复制
public class ValidateModelBase: INotifyDataErrorInfo, INotifyPropertyChanged
{
    private ConcurrentDictionary<string, List<string>> _errors =
        new ConcurrentDictionary<string, List<string>>();

    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged([CallerMemberName]string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
        ValidateAsync();
    }

    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

    public void OnErrorsChanged(string propertyName)
    {
        var handler = ErrorsChanged;
        if (handler != null)
            handler(this, new DataErrorsChangedEventArgs(propertyName));
    }

    public IEnumerable GetErrors(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName))
        {
            return null;
        }
        List<string> errorsForName;
        _errors.TryGetValue(propertyName, out errorsForName);
        return errorsForName;
    }

    public bool HasErrors
    {
        get { return _errors.Any(kv => kv.Value != null && kv.Value.Count > 0); }
    }

    public Task ValidateAsync()
    {
        return Task.Run(() => Validate());
    }

    private object _lock = new object();
    public void Validate()
    {
        lock (_lock)
        {
            var validationContext = new ValidationContext(this, null, null);
            var validationResults = new List<ValidationResult>();
            Validator.TryValidateObject(this, validationContext, validationResults, true);

            foreach (var kv in _errors.ToList())
            {
                if (validationResults.All(r => r.MemberNames.All(m => m != kv.Key)))
                {
                    List<string> outLi;
                    _errors.TryRemove(kv.Key, out outLi);
                    OnErrorsChanged(kv.Key);
                }
            }

            var q = from r in validationResults
                    from m in r.MemberNames
                    group r by m into g
                    select g;

            foreach (var prop in q)
            {
                var messages = prop.Select(r => r.ErrorMessage).ToList();

                if (_errors.ContainsKey(prop.Key))
                {
                    List<string> outLi;
                    _errors.TryRemove(prop.Key, out outLi);
                }
                _errors.TryAdd(prop.Key, messages);
                OnErrorsChanged(prop.Key);
            }
        }
    }
}

问题是它的工作正常,但当窗口打开时,文本框已经是红色的。我想让它在启动时忽略验证,只在我单击保存时验证。单击保存时,它将验证并查看是否有任何错误。当出现错误时,将设置验证(现在应标记为红色),并且窗口保持打开状态。我如何才能做到这一点。

EN

回答 1

Stack Overflow用户

发布于 2018-01-29 22:43:38

如果您的模型应该只在保存时验证,我会让您的模型实现IEditableObject,并确保在进行更改之前调用BeginEdit,并在提交这些更改(即保存)之前调用EndEdit

让基类跟踪它是否处于“编辑模式”,如果处于“编辑模式”,则禁止任何验证。当调用EndEdit时,再次允许验证并触发ErrorsChanged。如何处理CancelEdit由您决定。

一些控件,如数据网格,具有对IEditableObject的内置支持,并在开始编辑行时调用BeginEdit,在提交行时调用EndEdit。这是一个非常有用的界面。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48499407

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档