How do you get the WPF error template to appear on a control within a UserControl in WPF?
I have a UserControl containing two Labels, two TextBoxes, and a CheckBox. One of the TextBoxes represents the name of the entity and it is bound to a Name property off of a Model property exposed by my ViewModel, which is the DataContext of my Window. The Model class implements the IDataErrorInfo interface and I have confirmed through Unit Testing that when the Name is blank an error is returned through the property indexer implementation. I have bound to the Dependency Property backing the Name TextBox in my UserControl and when the validation error is encountered the WPF error template places a red border around the entire UserControl rather than just the Name TextBox.
The binding to the name field of the UserControl is as follows.
<vc:MyUserControl ItemName="{Binding Model.Name, ValidatesOnDataErrors=True}" />
A simiplified version of my UserControl and the backing DependencyProperty is as follows.
<UserControl>
<Grid>
<TextBox Text="{Binding ItemName}" />
</Grid>
</UserControl>
public partial class MyUserControl: UserControl
{
public static readonly DependencyProperty ItemNameProperty =
DependencyProperty.Register(
"ItemName",
typeof(string),
typeof(MyUserControl),
new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)
);
public string ItemName
{
get { return (string)GetValue(ItemNameProperty); }
set { SetValue(ItemNameProperty, value); }
}
}
The information I have found relating to this issue thus far has all been in regards to Silverlight or using a converter to not show the red border (which did not make sense to me). This information was all found here on stackoverflow.
Has anyone been able to solve this issue with WPF? Am I overlooking something obvious?
The ErrorTemplate
for UserControl
will be used if bindings to your UserControl
use ValidatesOnDataErrors=True
. But you can remove the red border with the Validation.ErrorTemplate Attached Property.
All controls within your UserControl
will only show a red border if you validate their bindings by implementing IDataErrorInfo
for the backing DependencyProperties too.
public class MyUserControl : UserControl, IDataErrorInfo
{
public static readonly DependencyProperty ItemNameProperty =
DependencyProperty.Register(
"ItemName",
typeof(string),
typeof(MyUserControl),
new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)
);
public string ItemName
{
get { return (string)GetValue(ItemNameProperty); }
set { SetValue(ItemNameProperty, value); }
}
public string Error
{
get { throw new NotImplementedException(); }
}
public string this[string columnName]
{
get
{
// use a specific validation or ask for UserControl Validation Error
return Validation.GetHasError(this) ? "UserControl has Error" : null;
}
}
}
and here the simplified XAML
<UserControl Validation.ErrorTemplate="{x:Null}">
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
<TextBox Text="{Binding ItemName, ValidatesOnDataErrors=True}" />
</Grid>
</UserControl>
Addition
If you want to differentiate between errors you can get the BindingExpression for your DependencyProperty and check the HasError Property.
BindingExpression be = BindingOperations.GetBindingExpression(this, ItemNameProperty);
return be != null && be.HasError ? "ItemName has Error" : null;