Wii*_*axx 7 c# validation xaml mvvm
目前我正面临着一个我无法解决的荒谬问题
我写了一个小包装器,它包装了几乎所有的Property并添加了一个Property但我不知道如何通过他将验证传递给我的XAML
这是我的代码
XAML
<TextBox Height="23" HorizontalAlignment="Left" Margin="42,74,0,0" Name="textBox2" VerticalAlignment="Top" Width="120"
DataContext="{Binding TB2}"/>
<!-- this Style is be added to the parent of TextBox -->
<Style TargetType="{x:Type TextBox}">
<Setter Property="Text" Value="{Binding Value,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsDirty}" Value="true">
<Setter Property="BorderBrush" Value="Orange"/>
</DataTrigger>
</Style.Triggers>
</Style>
Run Code Online (Sandbox Code Playgroud)
视图模型
public class vm : IDataErrorInfo, INotifyPropertyChanged
{
[Required]
[Range(4, 6)]
public string TB1 { get; set; }
[Required]
[Range(4, 6)]
public myWrapper TB2
{
get { return tb2; }
set{
tb2 = value;
OnPropertyChanged("TB2");
}
}
private myWrapper tb2;
public vm()
{
TB1 = "";
tb2 = new myWrapper("T");
}
#region IDataErrorInfo
private Dictionary<string, string> ErrorList = new Dictionary<string, string>();
public string Error { get { return getErrors(); } }
public string this[string propertyName] { get { return OnValidate(propertyName); } }
private string getErrors()
{
string Error = "";
foreach (KeyValuePair<string, string> error in ErrorList)
{
Error += error.Value;
Error += Environment.NewLine;
}
return Error;
}
protected virtual string OnValidate(string propertyName)
{
if (string.IsNullOrEmpty(propertyName))
throw new ArgumentException("Invalid property name", propertyName);
string error = string.Empty;
var value = this.GetType().GetProperty(propertyName).GetValue(this, null);
var results = new List<ValidationResult>(2);
var context = new ValidationContext(this, null, null) { MemberName = propertyName };
var result = Validator.TryValidateProperty(value, context, results);
if (!result)
{
var validationResult = results.First();
error = validationResult.ErrorMessage;
}
if (error.Length > 0)
{
if (!ErrorList.ContainsKey(propertyName))
ErrorList.Add(propertyName, error);
}
else
if (ErrorList.ContainsKey(propertyName))
ErrorList.Remove(propertyName);
return error;
}
#endregion //IDataErrorInfo
#region INotifyPropertyChanged
// Declare the event
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
myWrapper
public class myWrapper : INotifyPropertyChanged
{
private object currentValue;
private object currentOriginal;
public object Value
{
get { return currentValue; }
set
{
currentValue = value;
OnPropertyChanged("Value");
OnPropertyChanged("IsDirty");
}
}
public bool IsDirty
{
get { return !currentValue.Equals(currentOriginal); }
}
#region cTor
public myWrapper(object original)
{
currentValue = original;
currentOriginal = original.Copy(); // creates an deep Clone
}
#endregion
#region INotifyPropertyChanged
// Declare the event
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
我还在myWrapper中测试了IDataErrorInfo但没有运气
小智 2
由于您的 TextBox 实际上绑定到包装器,因此您必须将 IDataErrorInfo 添加到包装器类。现在的问题是如何在实际 ViewModel 和包装器之间连接验证逻辑。
正如 johndsamuels 所说,您可以将委托传递到包装器中,如下所示:
#region cTor
private string _propertyName;
private Func<string, string> _validationFunc;
public myWrapper(string propertyName, object original, Func<string, string> validationFunc)
{
_propertyName = propertyName;
_validationFunc = validationFunc;
currentValue = original;
currentOriginal = original.Copy(); // creates an deep Clone
}
#endregion
Run Code Online (Sandbox Code Playgroud)
您还需要传递属性名称,因为实际的 ViewModel 可能会在同一方法中验证多个属性。在您实际的 ViewModel 中,您将 OnValidate 方法作为委托传递,那么就可以了。
现在你将陷入验证的困境。您正在使用数据注释。例如 RangeAttribute 只能验证 int、double 或 string。由于属性只能在编译时在类型级别定义,因此您甚至无法将这些属性动态传递到包装器中。您可以编写自定义属性或使用其他验证机制,例如企业库验证块。
希望它能有所帮助。
| 归档时间: |
|
| 查看次数: |
1684 次 |
| 最近记录: |