gpt4 book ai didi

c# - 如何通过包装器将 IDataErrorInfo 验证传递给 XAML

转载 作者:太空狗 更新时间:2023-10-29 20:30:59 26 4
gpt4 key购买 nike

目前我正面临一个我无法解决的荒谬问题

我写了一个小包装器,它包装了几乎所有属性并添加了一个属性,但我不知道如何通过他将验证传递给我的 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>

View 模型

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
}

我的包装器

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
}

我还在 myWrapper 中测试了 IDataErrorInfo,但没有成功

最佳答案

由于您的 TextBox 实际上绑定(bind)到包装器,因此您必须将 IDataErrorInfo 添加到包装器类。现在的问题是如何连接实际 ViewModel 和包装器之间的验证逻辑。

正如 johndsamuels 所说,您可以像这样将委托(delegate)传递给包装器:

#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

您还需要传递属性名称,因为实际的 ViewModel 可能会在同一方法中验证多个属性。在您的实际 ViewModel 中,您将 OnValidate 方法作为委托(delegate)传递,这样就没问题了。

现在您将陷入关于验证的两难境地。您正在使用数据注释。例如,RangeAttribute 只能验证 int、double 或 string。由于属性只能在编译时在类型级别定义,您甚至不能将这些属性动态传递到包装器中。您可以编写自定义属性或使用其他验证机制,例如企业库验证 block 。

希望对您有所帮助。

关于c# - 如何通过包装器将 IDataErrorInfo 验证传递给 XAML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17163675/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com