自定义控件中不显示Silverlight IDataErrorInfo消息';s文本框
我创建了一个自定义密码框用户控件,可以显示和隐藏密码。它只是将标准密码框与绑定到相同密码字符串属性的文本框交换。这一切都很好,但现在我的数据验证错误不再显示,尽管它们是在后台正确生成的。以下是来自我的用户控件的xaml:自定义控件中不显示Silverlight IDataErrorInfo消息';s文本框,silverlight,validation,user-controls,Silverlight,Validation,User Controls,我创建了一个自定义密码框用户控件,可以显示和隐藏密码。它只是将标准密码框与绑定到相同密码字符串属性的文本框交换。这一切都很好,但现在我的数据验证错误不再显示,尽管它们是在后台正确生成的。以下是来自我的用户控件的xaml: <UserControl x:Class="Controls.EAPPasswordBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas
<UserControl x:Class="Controls.EAPPasswordBox"
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" x:Name="_root">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Top">
<PasswordBox x:Name="pwdBox" Password="{Binding Password, Mode=TwoWay,ValidatesOnDataErrors=True}" />
<TextBox x:Name="txtBox" Text="{Binding Password, Mode=TwoWay,ValidatesOnDataErrors=True}" />
</StackPanel>
</Grid>
现在,当我在“自定义密码”框中输入文本时,验证逻辑会被调用,但不会显示。我必须为此调整我的用户控件吗
编辑:这是我的密码箱背后的代码:
public partial class EAPPasswordBox : UserControl, INotifyPropertyChanged
{
public bool ShowText
{
get { return (bool)GetValue(ShowTextProperty); }
set {
SetValue(ShowTextProperty, value);
if (value == true)
{
this.pwdBox.Visibility = System.Windows.Visibility.Collapsed;
this.txtBox.Visibility = System.Windows.Visibility.Visible;
}
else
{
this.pwdBox.Visibility = System.Windows.Visibility.Visible;
this.txtBox.Visibility = System.Windows.Visibility.Collapsed;
}
}
}
public string Password
{
get { return (string)GetValue(PasswordProperty); }
set { SetValue(PasswordProperty, value); }
}
private Visibility _PwdBoxVisibility;
public Visibility PwdBoxVisibility
{
get { return _PwdBoxVisibility; }
set
{
_PwdBoxVisibility = value; NotifyPropertyChanged("PwdBoxVisibility");
}
}
private Visibility _TxtBoxVisibility;
public Visibility TxtBoxVisibility
{
get { return _TxtBoxVisibility; }
set
{
_TxtBoxVisibility = value; NotifyPropertyChanged("TxtBoxVisibility");
}
}
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register("Password", typeof(string), typeof(EAPPasswordBox), null);
public static readonly DependencyProperty ShowTextProperty =
DependencyProperty.Register("ShowText", typeof(bool), typeof(EAPPasswordBox), new PropertyMetadata(OnShowTextPropertyChanged));
public EAPPasswordBox()
{
InitializeComponent();
this.pwdBox.SetBinding(PasswordBox.PasswordProperty, new System.Windows.Data.Binding() { Source = this, Path = new PropertyPath("Password"), Mode = BindingMode.TwoWay,ValidatesOnDataErrors=true });
this.txtBox.SetBinding(TextBox.TextProperty, new System.Windows.Data.Binding() { Source = this, Path = new PropertyPath("Password"), Mode = BindingMode.TwoWay, ValidatesOnDataErrors=true });
this.ShowText = false;
}
private static void OnShowTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
EAPPasswordBox passwordBox = d as EAPPasswordBox;
if (passwordBox != null)
{
passwordBox.ShowText=(bool)e.NewValue;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
第二次编辑:如果有人能在父窗口/控件的xaml中向我解释usercontrols绑定属性的基本知识,这也会有所帮助。我不太明白为什么usercontrol没有获得相应父视图viewmodel属性的属性更改事件,因为它是通过xaml绑定到这些属性的。这是我最后的解决方案。因为我意识到用户控件的DataContext自动成为父视图的ViewModel,所以我完全放弃了Password dependency属性的绑定。我在控件中引入了一个新参数,该参数必须设置为父视图模型的password属性。然后,我使用这个字符串在控件的已加载事件中手动绑定文本框和密码框。这是我的密码:
public partial class EAPPasswordBox : UserControl, INotifyPropertyChanged
{
public bool ShowText
{
get { return (bool)GetValue(ShowTextProperty); }
set {
SetValue(ShowTextProperty, value);
if (value == true)
{
this.pwdBox.Visibility = System.Windows.Visibility.Collapsed;
this.txtBox.Visibility = System.Windows.Visibility.Visible;
}
else
{
this.pwdBox.Visibility = System.Windows.Visibility.Visible;
this.txtBox.Visibility = System.Windows.Visibility.Collapsed;
}
}
}
public string PasswordPropertyName { get; set; }
private Visibility _PwdBoxVisibility;
public Visibility PwdBoxVisibility
{
get { return _PwdBoxVisibility; }
set
{
_PwdBoxVisibility = value; NotifyPropertyChanged("PwdBoxVisibility");
}
}
private Visibility _TxtBoxVisibility;
public Visibility TxtBoxVisibility
{
get { return _TxtBoxVisibility; }
set
{
_TxtBoxVisibility = value; NotifyPropertyChanged("TxtBoxVisibility");
}
}
public static readonly DependencyProperty ShowTextProperty =
DependencyProperty.Register("ShowText", typeof(bool), typeof(EAPPasswordBox), new PropertyMetadata(OnShowTextPropertyChanged));
public EAPPasswordBox()
{
InitializeComponent();
this.ShowText = false;
}
private static void OnShowTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
EAPPasswordBox passwordBox = d as EAPPasswordBox;
if (passwordBox != null)
{
passwordBox.ShowText=(bool)e.NewValue;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
private void _root_Loaded(object sender, RoutedEventArgs e)
{
this.pwdBox.SetBinding(PasswordBox.PasswordProperty, new System.Windows.Data.Binding() { Source = this.DataContext, Path = new PropertyPath(PasswordPropertyName), Mode = BindingMode.TwoWay, ValidatesOnDataErrors = true });
this.txtBox.SetBinding(TextBox.TextProperty, new System.Windows.Data.Binding() { Source = this.DataContext, Path = new PropertyPath(PasswordPropertyName), Mode = BindingMode.TwoWay, ValidatesOnDataErrors = true });
}
}
这是控件的XAML
<UserControl x:Class="GAB.EAP2011.Controls.EAPPasswordBox"
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" x:Name="_root" Loaded="_root_Loaded">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Top">
<PasswordBox x:Name="pwdBox" />
<TextBox x:Name="txtBox" />
</StackPanel>
</Grid>
以下是如何使用它:
<local:EAPPasswordBox x:Name="pwdBox"
Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="2" PasswordPropertyName="password" ShowText="{Binding showPassword,Mode=TwoWay}"></local:EAPPasswordBox>
现在您有了一个很好的密码可见性切换控件:)
欢迎评论 我解决了这个问题,将加载事件中控件中的文本/pw框直接绑定到viewmodel的属性。我从父视图的xaml传递控件的普通公共属性的值,以标识要绑定到哪个密码属性。稍后将发布完整的答案。谢谢你的提问和答案。我已经按照你的想法实现了同样的想法,但是我仍然得到了一个错误。你能寄给我完整的代码样本吗?
<UserControl x:Class="GAB.EAP2011.Controls.EAPPasswordBox"
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" x:Name="_root" Loaded="_root_Loaded">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Top">
<PasswordBox x:Name="pwdBox" />
<TextBox x:Name="txtBox" />
</StackPanel>
</Grid>
<local:EAPPasswordBox x:Name="pwdBox"
Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="2" PasswordPropertyName="password" ShowText="{Binding showPassword,Mode=TwoWay}"></local:EAPPasswordBox>