Gab*_*abe 13 c# validation silverlight xaml
我不确定为什么验证状态不会反映在我的用户控件中.我抛出异常但由于某种原因控件没有显示验证状态...当我Textbox在我的MainPage上使用标准(现在在我的例子中注释掉)时它显示错误状态,不确定为什么它不是当它包裹.
我已经减少了这一点,所以基本上它是一个包装的用户控件TextBox.我错过了什么?
MyUserControl XAML:
<UserControl x:Class="ValidationWithUserControl.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<TextBox x:Name="TextBox"/>
</Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)
MyUserControl代码背后:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MyUserControl_Loaded);
this.TextBox.Unloaded += new RoutedEventHandler(TextBox_Unloaded);
}
public string Value
{
get { return (string)base.GetValue(ValueProperty); }
set { base.SetValue(ValueProperty, value); }
}
public static DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value",
typeof(string),
typeof(MyUserControl),
new PropertyMetadata(null));
private void MyUserControl_Loaded(object sender, RoutedEventArgs e)
{
this.TextBox.SetBinding(TextBox.TextProperty, new Binding()
{
Source = this,
Path = new PropertyPath("Value"),
Mode = BindingMode.TwoWay,
ValidatesOnExceptions = true,
NotifyOnValidationError= true
});
}
private void TextBox_Unloaded(object sender, RoutedEventArgs e)
{
this.TextBox.ClearValue(TextBox.TextProperty);
}
}
Run Code Online (Sandbox Code Playgroud)
我的主页XAML:
<Grid x:Name="LayoutRoot" Background="LightBlue">
<StackPanel>
<uc:MyUserControl x:Name="UC" Value="{Binding Path=Value, Mode=TwoWay}" Height="20" Width="100" />
<!--TextBox x:Name="MS" Text="{Binding Path=Value, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}" Height="20" Width="100" /-->
</StackPanel>
</Grid>
Run Code Online (Sandbox Code Playgroud)
我的MainPage代码背后:
public partial class MainPage : UserControl
{
private Model model;
//private Model model2;
public MainPage()
{
InitializeComponent();
this.model = new Model("UC");
//this.model2 = new Model("MS");
this.UC.DataContext = this.model;
//this.MS.DataContext = this.model2;
}
}
Run Code Online (Sandbox Code Playgroud)
我的型号:
public class Model
{
public Model(string answer)
{
this.answer = answer;
}
private string answer;
public string Value
{
get
{
return this.answer;
}
set
{
if (!String.IsNullOrEmpty(value))
this.answer = value;
else
throw new Exception("Error");
}
}
}
Run Code Online (Sandbox Code Playgroud)
好吧,我终于想出了如何处理这个问题.
您需要做的是从原始绑定复制验证并将其发送到Textbox绑定.
要实现这一点,您需要做的第一件事是在用户控件中实现INotifyDataErrorInfo接口.然后,您必须验证用户控件以获取GetErrors函数的确切验证文本(可以使用Validation.GetErrors完成此操作).
这是一个基本的实现,它在VB中,但我相信你明白了.
Public Event ErrorsChanged(ByVal sender As Object, ByVal e As System.ComponentModel.DataErrorsChangedEventArgs) Implements System.ComponentModel.INotifyDataErrorInfo.ErrorsChanged
Public Function GetErrors(ByVal propertyName As String) As System.Collections.IEnumerable Implements System.ComponentModel.INotifyDataErrorInfo.GetErrors
Dim returnValue As System.Collections.IEnumerable = Nothing
Dim errorMessage As String = Nothing
If propertyName = "Value" Then
If Validation.GetErrors(Me).Count = 0 Then
errorMessage = ""
Else
errorMessage = Validation.GetErrors(Me).First.ErrorContent.ToString
End If
If String.IsNullOrEmpty(errorMessage) Then
returnValue = Nothing
Else
returnValue = New List(Of String)() From {errorMessage}
End If
End If
Return returnValue
End Function
Public ReadOnly Property HasErrors As Boolean Implements System.ComponentModel.INotifyDataErrorInfo.HasErrors
Get
Return Validation.GetErrors(Me).Any()
End Get
End Property
Run Code Online (Sandbox Code Playgroud)
接下来要做的就是通知你控制它变得无效.您必须在2个地方执行此操作.
第一个将在BindingValidationError事件上.第二个将在Value PropertyChangedCallback函数中(必须在注册DependencyProperty时指定)
Public Shared ValueProperty As DependencyProperty = DependencyProperty.Register("Value", GetType(String), GetType(XDateTimePicker), New PropertyMetadata(Nothing, AddressOf ValuePropertyChangedCallback))
Public Shared Sub ValuePropertyChangedCallback(ByVal dependencyObject As DependencyObject, ByVal dependencyPropertyChangedEventArgs As DependencyPropertyChangedEventArgs)
DirectCast(dependencyObject, MyUserControl).NotifyErrorsChanged("Value")
End Sub
Private Sub MyUserControl_BindingValidationError(ByVal sender As Object, ByVal e As System.Windows.Controls.ValidationErrorEventArgs) Handles Me.BindingValidationError
Me.NotifyErrorsChanged("Value")
End Sub
Public Sub NotifyErrorsChanged(ByVal propertyName As String)
RaiseEvent ErrorsChanged(Me, New System.ComponentModel.DataErrorsChangedEventArgs(propertyName))
End Sub
Run Code Online (Sandbox Code Playgroud)
大部分工作现在已完成,但您仍需要对绑定进行一些调整.
创建TextBox绑定时,需要将NotifyOnValidationError设置为False以避免原始绑定和Textbox绑定之间的通知循环. 需要将ValidatesOnExceptions,ValidatesOnDataErrors和ValidatesOnNotifyDataErrors设置为True.
Dim binding As New System.Windows.Data.Binding
binding.Source = Me
binding.Path = New System.Windows.PropertyPath("Value")
binding.Mode = Data.BindingMode.TwoWay
binding.NotifyOnValidationError = False
binding.ValidatesOnExceptions = True
binding.ValidatesOnDataErrors = True
binding.ValidatesOnNotifyDataErrors = True
Me.TextBox1.SetBinding(TextBox.TextProperty, binding)
Run Code Online (Sandbox Code Playgroud)
最后,您需要在XAML 中将NotifyOnValidationError和ValidatesOnNotifyDataErrors属性设置为True.
<uc:MyUserControl x:Name="UC" Value="{Binding Path=Value, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnNotifyDataErrors=True}" Height="20" Width="100" />
Run Code Online (Sandbox Code Playgroud)