- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我完全按照以下链接中的描述实现了 INotifyDataErrorInfo:
http://blog.micic.ch/net/easy-mvvm-example-with-inotifypropertychanged-and-inotifydataerrorinfo
我有一个 TextBox
,它绑定(bind)到我模型中的一个字符串属性。
XAML
<TextBox Text="{Binding FullName,
ValidatesOnNotifyDataErrors=True,
NotifyOnValidationError=True,
UpdateSourceTrigger=PropertyChanged}" />
型号
private string _fullName;
public string FullName
{
get { return _fullName; }
set
{
// Set raises OnPropertyChanged
Set(ref _fullName, value);
if (string.IsNullOrWhiteSpace(_fullName))
AddError(nameof(FullName), "Name required");
else
RemoveError(nameof(FullName));
}
}
INotifyDataError 代码
private Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>();
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
// get errors by property
public IEnumerable GetErrors(string propertyName)
{
if (_errors.ContainsKey(propertyName))
return _errors[propertyName];
return null;
}
public bool HasErrors => _errors.Count > 0;
// object is valid
public bool IsValid => !HasErrors;
public void AddError(string propertyName, string error)
{
// Add error to list
_errors[propertyName] = new List<string>() { error };
NotifyErrorsChanged(propertyName);
}
public void RemoveError(string propertyName)
{
// remove error
if (_errors.ContainsKey(propertyName))
_errors.Remove(propertyName);
NotifyErrorsChanged(propertyName);
}
public void NotifyErrorsChanged(string propertyName)
{
// Notify
if (ErrorsChanged != null)
ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
现在一切正常,但只有当我在我的文本框中输入内容时它才会生效。我想要一些方法来按需验证,甚至不触摸文本框,比如单击按钮。
我已尝试按照 this 中的描述为我的所有属性提高 PropertyChanged问题,但它没有检测到错误。我不知何故需要调用我的属性 setter ,以便可以检测到错误。我正在寻找 MVVM 解决方案。
最佳答案
恕我直言,您使用的 INotifyDataErrorInfo 实现有些缺陷。它依赖于附加到对象的状态(列表)中保存的错误。存储状态的问题是,有时,在移动的世界中,您没有机会在需要时更新它。这是另一个 MVVM 实现,它不依赖于存储的状态,而是动态计算错误状态。
处理方式略有不同,因为您需要将验证代码放在中央 GetErrors 方法中(您可以创建从该中央方法调用的每个属性的验证方法),而不是属性 setter 。
public class ModelBase : INotifyPropertyChanged, INotifyDataErrorInfo
{
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public bool HasErrors
{
get
{
return GetErrors(null).OfType<object>().Any();
}
}
public virtual void ForceValidation()
{
OnPropertyChanged(null);
}
public virtual IEnumerable GetErrors([CallerMemberName] string propertyName = null)
{
return Enumerable.Empty<object>();
}
protected void OnErrorsChanged([CallerMemberName] string propertyName = null)
{
OnErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
protected virtual void OnErrorsChanged(object sender, DataErrorsChangedEventArgs e)
{
var handler = ErrorsChanged;
if (handler != null)
{
handler(sender, e);
}
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
OnPropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(sender, e);
}
}
}
这里有两个示例类来演示如何使用它:
public class Customer : ModelBase
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged();
}
}
}
public override IEnumerable GetErrors([CallerMemberName] string propertyName = null)
{
if (string.IsNullOrEmpty(propertyName) || propertyName == nameof(Name))
{
if (string.IsNullOrWhiteSpace(_name))
yield return "Name cannot be empty.";
}
}
}
public class CustomerWithAge : Customer
{
private int _age;
public int Age
{
get
{
return _age;
}
set
{
if (_age != value)
{
_age = value;
OnPropertyChanged();
}
}
}
public override IEnumerable GetErrors([CallerMemberName] string propertyName = null)
{
foreach (var obj in base.GetErrors(propertyName))
{
yield return obj;
}
if (string.IsNullOrEmpty(propertyName) || propertyName == nameof(Age))
{
if (_age <= 0)
yield return "Age is invalid.";
}
}
}
使用像这样的简单 XAML,它就像一个魅力:
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding Age, UpdateSourceTrigger=PropertyChanged}" />
(UpdateSourceTrigger 是可选的,如果您不使用它,它只会在失去焦点时起作用)。
使用这个 MVVM 基类,您不必强制执行任何验证。但是如果您需要它,我已经在 ModelBase 中添加了一个应该可以工作的 ForceValidation 示例方法(我已经使用例如 _name 之类的成员值对其进行了测试,该值在不通过公共(public) setter 的情况下会被更改)。
关于c# - 强制 INotifyDataErrorInfo 验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34665650/
在绑定(bind)的情况下,例如 哪些类需要实现 INotifyDataErrorInfo: 数据上下文 一些项目 另一个项目 这些的一些组合 最佳答案 AnotherItem INotifyDat
我有点困惑 MSDN example . 目前尚不清楚如何处理和设置实体相关错误。 示例代码: public System.Collections.IEnumerable GetErrors(stri
我有一个 ObservableCollection 类型的数据集合(比如实例作为 myClassTypes)。在一些用户操作之后,这个 myClassTypes 填充了 ViewModel 中的值。在
UWP平台控件是否通过绑定(bind)自动支持INotifyDataErrorInfo接口(interface)? 在 Silverlight 和 WPF 上,如果我们实现 INotifyDataEr
我遇到了一个非常困惑的情况: 我打开了一个对话框,其中显示了一个带有 INotifyDataErrorInfo 的 View ,它立即返回一个错误(当文本字段不为空时),我看到了红色边框的错误通知:
我在 WPF 中使用 INotifyDataError 接口(interface)进行异步验证。我有属性(property) 在我的 View 模型上,我有一个属性 public SomeType
当 TextBox 为空时,我有一个简单的验证来显示错误消息。问题在于消息仅显示消息的第一个 字母。 在文本框样式中: 如果我将错误消息直接设置为 Setter 值,它会毫无问题地显示所
我正在尝试实现 INotifyDataErrorInfo,但在尝试验证 ObservableCollection 属性时没有成功。 问题是,如果集合有误,我会得到红色边框,但如果我更正集合,红色边框就
我正在尝试实现 INotifyDataErrorInfo,我的模型有一些自定义类型,需要根据其使用情况进行不同的验证。我不确定如何实现此验证。 我试图在下面创建一个简单的示例来展示我正在尝试完成的工作
我完全按照以下链接中的描述实现了 INotifyDataErrorInfo: http://blog.micic.ch/net/easy-mvvm-example-with-inotifyproper
我有一个实现 INotifyDataErrorInfo 的 View 模型。我将一个文本框绑定(bind)到这样的 View 模型属性之一: 数据绑定(bind)有效,但是当我添加如下验证错误时 U
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我应该使用 IDataErrorInfo、INotifyDataErrorInfo 还是两者都使用? 如果我同时使用两者,我应该在两者中提供相同的错误,还是只提供来自 IDataErrorInfo 的
上下文 我正在使用 MVVM 和 Entity Framework (数据库优先)开发 WPF 应用程序。我有一个机身对象的 ObservableCollection(通过 CollectionVie
我有一个实现 INotifyPropertyChanged 的模型和 INotifyDataErrorInfo .每当我修改了属性时,就会触发 Property changed 事件,但由于某种原因,
我是 WPF 新手,开始学习下面的教程。 http://social.technet.microsoft.com/wiki/contents/articles/19490.validating-dat
我正在使用 INotifyDataErrorInfo 接口(interface)来实现通用的 MVVM 验证机制。我通过调用 OnValidate 而不是 OnPropertyChanged 来实现接
我正试图找到一个优雅的解决方案来使用 Caliburn.Micro MVVM 框架实现 INotifiyDataErrorInfo。 我想限制将在每个需要实现验证的虚拟机中重复的代码量。我首先编写了一
这是一个奇怪的问题,此时我认为这可能与我的机器配置有关。 基本上我已经创建了一个非常标准的 INotifyDataErrorInfo 实现。在某些情况下,当提高 ErrorsChanged事件我得到一
我想我的问题是validationsummary到底是如何确定它要显示的内容的? 我有一个实现 INotifyDataErrorInfo 的 View 模型,一些验证错误显示在我的验证摘要中,而其他错
我是一名优秀的程序员,十分优秀!