- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在开发一个采用 MVVM 模式的 WPF 应用程序,我在其中使用 DataAnnotations 进行验证。所以我在这个 article 中实现了类似的解决方案.
然后我尝试向我的 View 模型添加一个属性 - 称为“年龄” - 它只接受数字并且范围在 1 到 100 之间。
[RegularExpression(@"^[0-9]{1,3}$", ErrorMessage = "Please enter a valid number")]
[Range(1, 100, ErrorMessage = "Age should be between 1 to 100")]
/// <summary>
/// Gets or sets the age.
/// </summary>
public int Age
{
get { return GetValue(() => Age); }
set { SetValue(() => Age, value); }
}
在我的 WPF 窗口上,我得到了一个绑定(bind)到 Age 的文本框:
<TextBox x:Name="tbx_age"
ToolTip="The age"
Text="{Binding Age, NotifyOnSourceUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}">
</TextBox>
当我启动应用程序时,文本框预分配了零(“0”)。当我用“1a”替换文本框中的零时,我收到错误消息“无法转换值‘1a’”。这不是来 self 的代码的常规消息,我无法解释它的来源。我是否在正则表达式或其他方面犯了错误?
我已经将我的测试项目上传到 GitHub: Repository我指的项目名为“Validation_DataAnnotations”。
提前致谢!
这是我用于通知和验证的 PropertyChangedNotification 类:
public abstract class PropertyChangedNotification : INotifyPropertyChanged, IDataErrorInfo
{
#region Fields
private readonly Dictionary<string, object> _values = new Dictionary<string, object>();
#endregion
#region Protected
/// <summary>
/// Sets the value of a property.
/// </summary>
/// <typeparam name="T">The type of the property value.</typeparam>
/// <param name="propertySelector">Expression tree contains the property definition.</param>
/// <param name="value">The property value.</param>
protected void SetValue<T>(Expression<Func<T>> propertySelector, T value)
{
string propertyName = GetPropertyName(propertySelector);
SetValue<T>(propertyName, value);
}
/// <summary>
/// Sets the value of a property.
/// </summary>
/// <typeparam name="T">The type of the property value.</typeparam>
/// <param name="propertyName">The name of the property.</param>
/// <param name="value">The property value.</param>
protected void SetValue<T>(string propertyName, T value)
{
if (string.IsNullOrEmpty(propertyName))
{
throw new ArgumentException("Invalid property name", propertyName);
}
_values[propertyName] = value;
NotifyPropertyChanged(propertyName);
}
/// <summary>
/// Gets the value of a property.
/// </summary>
/// <typeparam name="T">The type of the property value.</typeparam>
/// <param name="propertySelector">Expression tree contains the property definition.</param>
/// <returns>The value of the property or default value if not exist.</returns>
protected T GetValue<T>(Expression<Func<T>> propertySelector)
{
string propertyName = GetPropertyName(propertySelector);
return GetValue<T>(propertyName);
}
/// <summary>
/// Gets the value of a property.
/// </summary>
/// <typeparam name="T">The type of the property value.</typeparam>
/// <param name="propertyName">The name of the property.</param>
/// <returns>The value of the property or default value if not exist.</returns>
protected T GetValue<T>(string propertyName)
{
if (string.IsNullOrEmpty(propertyName))
{
throw new ArgumentException("Invalid property name", propertyName);
}
object value;
if (!_values.TryGetValue(propertyName, out value))
{
value = default(T);
_values.Add(propertyName, value);
}
return (T)value;
}
/// <summary>
/// Validates current instance properties using Data Annotations.
/// </summary>
/// <param name="propertyName">This instance property to validate.</param>
/// <returns>Relevant error string on validation failure or <see cref="System.String.Empty"/> on validation success.</returns>
protected virtual string OnValidate(string propertyName)
{
if (string.IsNullOrEmpty(propertyName))
{
throw new ArgumentException("Invalid property name", propertyName);
}
string error = string.Empty;
var value = GetValue(propertyName);
var results = new List<System.ComponentModel.DataAnnotations.ValidationResult>(1);
var result = Validator.TryValidateProperty(
value,
new ValidationContext(this, null, null)
{
MemberName = propertyName
},
results);
if (!result)
{
var validationResult = results.First();
error = validationResult.ErrorMessage;
}
return error;
}
#endregion
#region Change Notification
/// <summary>
/// Raised when a property on this object has a new value.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected void NotifyPropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
protected void NotifyPropertyChanged<T>(Expression<Func<T>> propertySelector)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
string propertyName = GetPropertyName(propertySelector);
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion // INotifyPropertyChanged Members
#region Data Validation
string IDataErrorInfo.Error
{
get
{
throw new NotSupportedException("IDataErrorInfo.Error is not supported, use IDataErrorInfo.this[propertyName] instead.");
}
}
string IDataErrorInfo.this[string propertyName]
{
get
{
return OnValidate(propertyName);
}
}
#endregion
#region Privates
private string GetPropertyName(LambdaExpression expression)
{
var memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
{
throw new InvalidOperationException();
}
return memberExpression.Member.Name;
}
private object GetValue(string propertyName)
{
object value;
if (!_values.TryGetValue(propertyName, out value))
{
var propertyDescriptor = TypeDescriptor.GetProperties(GetType()).Find(propertyName, false);
if (propertyDescriptor == null)
{
throw new ArgumentException("Invalid property name", propertyName);
}
value = propertyDescriptor.GetValue(this);
_values.Add(propertyName, value);
}
return value;
}
#endregion
#region Debugging
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
[Conditional("DEBUG")]
[DebuggerStepThrough]
public void VerifyPropertyName(string propertyName)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
{
string msg = "Invalid property name: " + propertyName;
if (this.ThrowOnInvalidPropertyName)
throw new Exception(msg);
else
Debug.Fail(msg);
}
}
/// <summary>
/// Returns whether an exception is thrown, or if a Debug.Fail() is used
/// when an invalid property name is passed to the VerifyPropertyName method.
/// The default value is false, but subclasses used by unit tests might
/// override this property's getter to return true.
/// </summary>
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
#endregion // Debugging Aides
}
最佳答案
因为 int
属性不能永远设置为 int
值以外的任何值,所以如果您设置,您的属性 setter 将永远不会被调用将 TextBox 的 Text 属性设置为“1a”。世界上没有正则表达式或数据注释可以解决这个问题。
要自定义当 WPF 运行时在设置属性之前将值“1a”转换为 int
时出现的错误消息,您可以使用 ValidationRule
:
<TextBox>
<TextBox.Text>
<Binding Path="Age" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:StringToIntValidationRule ValidationStep="RawProposedValue"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
...
</TextBox>
public class StringToIntValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
{
int i;
if (int.TryParse(value.ToString(), out i))
return new ValidationResult(true, null);
return new ValidationResult(false, "Please enter a valid integer value.");
}
}
以下博客文章提供了完整示例和更多相关信息:https://blog.magnusmontin.net/2013/08/26/data-validation-in-wpf/
请注意,验证其 Age 属性是否设置为 int
值不是 View 模型的责任。这是控件或 View 的责任。
关于c# - 如何使用 DataAnnotations 检查 WPF 中的无效数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41936211/
我无法将元数据类型附加到我们应用程序中自动生成的类。我测试了在生成的类中设置 Order 属性,它工作正常,但如果尝试使用另一个类,我以后将无法获取属性。 我也已经尝试了建议的解决方案 here没有成
我正在尝试使用 razor 页面验证用户以密码形式输入的内容。我有以下模型 public class UserPassword { public Guid? Id{ g
我想将 DataAnnotations 存储在数据库中。如何通过反射(或其他方式)检索 DataAnnotation 的字符串表示形式? 示例 public class Product {
我正在为我的表单使用数据注释,用户可以在其中注册他们的帐户。对于电子邮件字段,我有一个数据注释用于必填,一个用于有效电子邮件。在这里你可以在我的 View 模型中看到: [Required(E
我有一个我创建的 DataAnnotationValidator。我目前正在尝试使用 Required Field 属性对其进行测试,并且当我的属性为 null 时,我无法使 IsValid 属性失败
如何在DataFormatString中显示完整的月份名称和年份?(2014年11月) 我尝试使用这个 DataAnnotation,但它没有给我想要的 o/p: [DisplayFormat(Da
我想将 View 模型上的 DataAnnotation 设置为可通过 web.config 配置的动态值。在下面的示例中,我收到此错误“属性参数必须是属性参数类型的常量表达式、typeof 表达式或
我有一个 Entity Framework 为我生成的类: 模型/EF.tt/Product.cs public partial class X { public int Name { get;
在允许发布表单之前,是否有任何方法可以使用数据注释来比较两个表单字段(例如确认电子邮件地址)是否相同? 例如。正则表达式数据注释可以使用匹配函数来引用 ViewModel 中的另一个属性吗? 最佳答案
有人可以指向我介绍该新 namespace 的网络广播或教程/视频,以及如何使用它来帮助验证诸如用户输入之类的数据吗? 最佳答案 试试这个(对不起,不是视觉上的): ASP.NET MVC Tip #
我正在尝试在 ASP.net MVC 应用程序之外使用 DataAnnotation 属性验证。理想情况下,我想在我的控制台应用程序中使用任何模型类并将其装饰如下: private class MyE
DataAnnotations 和 Application Validation Block 有什么区别? 最佳答案 DataAnnotations 是一种基于属性的模型,用于“注释”您的数据,它位于
我正在使用 System.ComponontModel.DataAnnotations 来验证我的模型对象。如何替换消息标准属性(Required 和 StringLength)而不为每个消息提供 E
DataAnnotations 与 IDataErrorInfo 两者的优点和缺点? 一个比另一个的好处? (尤其是与 MVC 相关的) 最佳答案 因为我不想开始一个新问题,所以迟到了讨论。我的出发点
我正在尝试使用 DataAnnotations 对类执行手动验证。该应用程序是一个控制台应用程序,因此不涉及 MVC。我正在使用 .NET 4.0。 我的指导来自 this article :唯一的区
我只是期待创建一个没有连续数字重复超过五次的正则表达式,并且它应该只从 6、7、8、9 位数字开始。 我有解决方案,但我正在使用以下 2 个正则表达式并进行验证。 string startPatter
我有一个属性: [MaxLength(3)] public string State { get; set; } 在名为 State 的属性上我只希望它匹配澳大利亚的 5 个州:{ "VIC", "N
如何在不使用 MVC 库的情况下验证包含 DataAnnotations 的实体?当您在表示层中时使用 Model.IsValid 很好,但是当您想要确保模型在域/业务层中有效时怎么办?我需要一个单独
北美的日期格式是 MM/dd/yyyy 我正在为澳大利亚开发项目 (asp.net MVC 2),其中日期格式为 d/MM/yyyy 在 web.config 我有 在 views
当我们使用 EF (例如)通过 MVC , 我们可以使用 ModelState.IsValid检测 model可以通过DataAnnotations元数据与否。但是如何使用 DataAnnotatio
我是一名优秀的程序员,十分优秀!