W tej chwili jestem stoi to śmieszny problem, który nie jestem w stanie naprawićJak przekazać IDataErrorInfo Walidacja poprzez owinięcie do XAML
pisałem trochę owijkę, która otacza niemal dowolny obiekt i dodano jedną właściwość ale nie wiem jak przekazać zatwierdzaniu przez niego do mojego XAML
Oto mój kod
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>
ViewModel
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
}
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
}
ja również testowane IDataErrorInfo w myWrapper bez powodzenia
IDataErrorInfo w myWrapper powinien pracować – blindmeis
@ blindmeis już go przetestowałem i tak nie jest, ponieważ 'Value' nie ma żadnych metadanych, więc zawsze będzie ważne, muszę uzyskać te informacje w jakiś sposób z mojego' vm' – WiiMaxx
mam na myśli, że powinien działać od strony wpf - jeśli więc zaimplementujesz idataerrorinfo bez atrybutów w mywrapper do testowania - powinieneś zobaczyć walidację w wpf ui. afaik wpf - podczas wiązania z mywrapper - przechodzi do obiektu mywrapper, aby sprawdzić idataerrorinfo dla valdation. więc musisz go zaimplementować tam w dowolny sposób – blindmeis