关于Silverlight Input Data Validation <一>里已经讲过如何用INotifyPropertyChanged接口来实现数据的Validation。
现在问题来了,用INotifyPropertyChanged接口来实现数据Validation,会有红色ToolTip绑定到目标控件上。
这是好事,但如果我们不想让验证信息绑定到目标控件上,而是让它显示到其他地方,如显示到TextBlock上,如何做呢?
关于INotifyDataErrorInfo接口的介绍,详见MSDN INotifyDataErrorInfo Interface。
要点:
1.ValidatesOnNotifyDataErrors在默认情况下是True的,所以,不想让验证失败的消息显示出来,请把它设置为False。
2.请指定你所要验证地控件的DataContext。
3.INotifyPropertyChanged接口里有个方法GetErrors(),实现它,并让他返回你想要的东西,比如返回error内容。
以下是我的代码:
(1)xaml部分:
//对应上面的要点1
<TextBox Text="{Binding Mode=TwoWay, Path=MyID, ValidatesOnNotifyDataErrors=False}" Height="25" Name="txtMyID" Width="100" />
<Button Content="Click" Height="25" HorizontalAlignment="Center" Name="btnClick" Click="btnClick_Click" VerticalAlignment="Top" Width="80" />
<TextBlock Height="25" HorizontalAlignment="Left" Name="tbErrorMsg" VerticalAlignment="Center" Width="140" />
(2)xaml.cs部分:
public partial class MainPage : UserControl
{
MyPageValidation mv;
public MainPage()
{
InitializeComponent();
//对应上面的要点2
mv = new MyPageValidation();
txtMyID.DataContext = mv;
}
private void btnClick_Click(object sender, RoutedEventArgs e)
{
this.tbErrorMsg.Text = string.Empty;
if(mv.HasErrors)
{
//对应上面的要点3
List<String> errors = (List<String>)mv.GetErrors("MyID");
if (errors != null)
{
this.tbErrorMsg.Text = errors[0];
this.tbErrorMsg.Foreground = new SolidColorBrush(Colors.Red);
}
}
}
}
(3)MyPageValidation验证类部分:
public class MyPageValidation : INotifyDataErrorInfo
{
private string _MyID;
public string MyID
{
get { return _MyID; }
set {
if (IsIdValid(value) && _MyID != value) _MyID = value;
}
}
public bool IsIdValid(string value)
{
bool isValid = true;
int resultOut = 0;
if (!Int32.TryParse(value,out resultOut))
{
AddError("MyID", ID_ERROR);
isValid = false;
}
else RemoveError("MyID", ID_ERROR);
return isValid;
}
private Dictionary<String, List<String>> errors = new Dictionary<string, List<string>>();
private const string ID_ERROR = "Please enter Integer!";
public void AddError(string propertyName, string error)
{
if (!errors.ContainsKey(propertyName))
errors[propertyName] = new List<string>();
if (!errors[propertyName].Contains(error))
{
errors[propertyName].Insert(0, error);
RaiseErrorsChanged(propertyName);
}
}
public void RemoveError(string propertyName, string error)
{
if (errors.ContainsKey(propertyName) &&
errors[propertyName].Contains(error))
{
errors[propertyName].Remove(error);
if (errors[propertyName].Count == 0) errors.Remove(propertyName);
RaiseErrorsChanged(propertyName);
}
}
public void RaiseErrorsChanged(string propertyName)
{
if (ErrorsChanged != null)
ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
#region INotifyDataErrorInfo Members
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
//对应上面的要点3
public System.Collections.IEnumerable GetErrors(string propertyName)
{
if (String.IsNullOrEmpty(propertyName) ||
!errors.ContainsKey(propertyName)) return null;
return errors[propertyName];
}
public bool HasErrors
{
get { return errors.Count > 0; }
}
#endregion
}