I have the following user control (Realy a TextBox control now):
<TextBox:Class="IM.Common.UIControls.IMTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
>
<Validation.ErrorTemplate>
<ControlTemplate>
<!--Show this if there is a validation error-->
<StackPanel Orientation="Horizontal" ToolTip="{Binding [0].ErrorContent}" >
<Border BorderThickness="2" BorderBrush="Orange" >
<AdornedElementPlaceholder Margin="-1" />
</Border>
</StackPanel>
</ControlTemplate>
</Validation.ErrorTemplate>
</TextBox>
Code Behind:
namespace IM.Common.UIControls
{
public partial class IMTextBox
{
public IMTextBox()
{
InitializeComponent();
}
}
}
I have the Following Model:
public class User : IDataErrorInfo, INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
#endregion
// used just to know if passwords match
public string Password2
{
get { return _password2; }
set
{
_password2 = value;
OnPropertyChanged("Password2");
}
}
private string _password2;
public string Error
{
get
{
throw new NotImplementedException();
}
}
public string this[string columnName]
{
get
{
if (columnName == "Password2")
{
if (string.IsNullOrEmpty(Password2))
return "required";
if (Regex.Match(Password2, "\\s").Success)
return "Password cannot contain spaces";
}
return null;
}
}
}
When I use that "usercontrol" as:
<myControls:IMTextBox Text="{Binding SomeUser.Password2, ValidatesOnDataErrors=true, NotifyOnValidationError=true}" />
It works amazing! Validation errors show and it works as expected.
Now here is my problem :/
I want to add a label to that user control and have validations still work. As a result the root of my usercontrol can no longer be the TextBox itself. As a result I modified the usercontrol to look like:
<UserControl:Class="IM.Common.UIControls.IMTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
>
<StackPanel>
<TextBlock Text="{Binding LabelTxt}" />
<TextBox Text="{Binding Txt, ValidatesOnDataErrors=true, NotifyOnValidationError=true}">
<Validation.ErrorTemplate>
<ControlTemplate>
<!--Show this if there is a validation error-->
<StackPanel Orientation="Horizontal" ToolTip="{Binding [0].ErrorContent}" >
<Border BorderThickness="2" BorderBrush="Orange" >
<AdornedElementPlaceholder Margin="-1" />
</Border>
</StackPanel>
</ControlTemplate>
</Validation.ErrorTemplate>
</TextBox>
</StackPanel>
</UserControl>
The code behind now looks like:
namespace IM.Common.UIControls
{
public partial class IMTextBox : UserControl
{
public IMTextBox()
{
InitializeComponent();
this.DataContext = this;
}
public string Txt
{
get
{
return (string)GetValue(TxtProperty);
}
set
{
SetValue(TxtProperty, value);
}
}
public static DependencyProperty TxtProperty = DependencyProperty.Register(
name: "Txt",
propertyType: typeof(string),
ownerType: typeof(IMTextBox),
typeMetadata: new FrameworkPropertyMetadata(
defaultValue: string.Empty
)
);
}
}
Now when I try to use the usercontrol I am able to do:
<myControls:IMTextBox Txt="{Binding SomeUser.Password2, ValidatesOnDataErrors=true, NotifyOnValidationError=true}" />
But the validation error no longer fires :( . In other words if I where to enter "foo foo" the textbox will turn orange on the first example but not on the last example where the root control is a UserControl instead of a TextBox.
How can I still make validation work?
Edit
Thanks to the answer from alek kowalczyk I googled his solution because I did not understood his answer and came up with this solution:
The DataContext of your UserControl is different from the one of your Window, so the validation error doesn't get to the textbox, I would suggest to do an custom control derived from TextBox instead of an user control.
Here you have a control template for a textbox with a label, you can store the control template in a resource dictionary if you want to reuse it on several textboxes: