Прекарах последния час или повече в гугъл за отговор на това, но почти всеки резултат е или в ASP.NET, или говори за подходи на Code First, които са безполезни за мен.
По принцип имам POCO обекти на базата данни на първи обект, за които предоставям проверка за използване на IDataErrorInfo.
Сега това работи добре, освен че имам индексатор, който е дълъг 200 реда с около 40 оператора if в него. (Сериозен съм.)
Това, което правя в момента, е да разширя класовете така:
public partial class MyPocoObject : IDataErrorInfo
{
public string Error
{
get { throw new NotImplementedException("IDataErrorInfo.Error"); }
}
public string this[string columnName]
{
get
{
string result = null;
// There's about 40 if statements here...
}
}
}
Ясно е, че това е грешно, така че се опитвам да използвам DataAnnotations вместо това.
Това е, което разбрах досега.
Създадох класове метаданни така:
[MetadataType(typeof(MyObjectMetaData))]
public partial class MyObject { }
public class MyObjectMetaData
{
[Required(AllowEmptyStrings = false, ErrorMessage = "Forename is a required field.")]
public string Forename;
}
След това имам контролите, декларирани като такива:
<TextBox Text="{Binding SelectedObject.Forename, NotifyOnValidationError=True, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"/>
Тогава имам тригер на друго място:
<Style TargetType="TextBox" BasedOn="{StaticResource Global}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self},Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
Когато направих това с IDataErrorInfo, когато проверката се провали, щях да получа червена рамка и подсказка със съобщението за грешка. Използвайки анотации към данни, не получавам нищо.
Как трябва да прилагам това? Защото 40 оператора if в един метод е лудост.
Актуализация: Опитах кода, предложен в отговорите, който не работи, въпреки че мисля, че съм направил това погрешно.
public partial class Member : IDataErrorInfo
{
// Error: The type 'Project.Client.Models.Member' already contains a definition for 'Forename'
[Required(AllowEmptyStrings = false, ErrorMessage = "Forename is a required field.")]
public string Forename;
private readonly Dictionary<string, object> _values = new Dictionary<string, object>();
public string Error
{
get { throw new NotImplementedException("IDataErrorInfo.Error"); }
}
public string this[string columnName]
{
get { return OnValidate(columnName); }
}
protected virtual string OnValidate(string propertyName)
{
if (string.IsNullOrEmpty(propertyName))
{
throw new ArgumentException("Invalid property name", propertyName);
}
string error = string.Empty;
// Error: Project.Client.Models.Member.GetValue<T>(string)' cannot be inferred from the usage. Try specifying the type arguments explicitly
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;
}
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;
}
}
Актуализация 2: Кодът, свързан в статията за MVVM, изглежда работи, но все още не се показват съобщения за грешка, въпреки че OnValidate се задейства.
Въпреки че нещо друго не е наред сега... въпреки че съдържанието на текстовото поле се променя, стойността, върната от GetValue, винаги е една и съща и върху празен обект, който не е зареден от моята база данни, валидирането изобщо не се задейства.