Error Pattern Design

It seems I read another question / answer on this site about this problem, but I can’t remember what the answer was, and now I can’t find the original post.

I am not a fan of the default error pattern in WPF. I understand how to change this error pattern. However, if I add some content to the end of, say, a text field, the size of the text field will not change, and the added content will (potentially) be cropped. How to change the text box (I believe that the correct terminology is a decorated element) in this scenario, so that nothing is cropped?

Here is the XAML template for the error template:

<Style TargetType="{x:Type TextBox}"> <Setter Property="Validation.ErrorTemplate"> <Setter.Value> <ControlTemplate> <StackPanel> <AdornedElementPlaceholder /> <TextBlock Foreground="Red" Text="Error..." /> </StackPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> 

Here is the XAML for several text fields in the form:

 <StackPanel> <TextBox Text="{Binding...}" /> <TextBox /> </StackPanel> 
+8
wpf xaml
source share
1 answer

two weeks ago I ran into the same problem.

I came up with a solution after seeing this blog post by Josh Smith.

http://joshsmithonwpf.wordpress.com/2008/10/08/binding-to-validationerrors0-without-creating-debug-spew/

The trick is to define a DataTemplate to render the ValidationError object, and then use ContentPresenter to display the error message. If there is no error, then ContentPresenter will not be displayed.

Below I shared the code of the sample application I created.

Without errorsWith errors

Here is the XAML:

 <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" SizeToContent="WidthAndHeight" Title="MainWindow"> <StackPanel Margin="5"> <StackPanel.Resources> <DataTemplate DataType="{x:Type ValidationError}"> <TextBlock Text="{Binding ErrorContent}" Foreground="White" Background="Red" VerticalAlignment="Center" FontWeight="Bold"/> </DataTemplate> </StackPanel.Resources> <TextBox Name="TextBox1" Text="{Binding Text1, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/> <ContentPresenter Content="{Binding ElementName= TextBox1, Path=(Validation.Errors).CurrentItem}" HorizontalAlignment="Left"/> <TextBox Name="TextBox2" Text="{Binding Text2, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/> <ContentPresenter Content="{Binding ElementName= TextBox2, Path=(Validation.Errors).CurrentItem}" HorizontalAlignment="Left"/> <Button Content="Validate" Click="Button_Click"/> </StackPanel> </Window> 

File Code:

 namespace WpfApplication1 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private ViewModel _ViewModel = null; public MainWindow() { InitializeComponent(); _ViewModel = new ViewModel(); DataContext = _ViewModel; } private void Button_Click(object sender, RoutedEventArgs e) { _ViewModel.Validate = true; _ViewModel.OnPropertyChanged("Text1"); _ViewModel.OnPropertyChanged("Text2"); } } } 

ViewModel:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; namespace WpfApplication1 { public class ViewModel : INotifyPropertyChanged, IDataErrorInfo { private string _Text1; public string Text1 { get { return _Text1; } set { _Text1 = value; OnPropertyChanged("Text1"); } } private string _Text2; public string Text2 { get { return _Text2; } set { _Text2 = value; OnPropertyChanged("Text2"); } } public bool Validate { get; set; } #region INotifyPropertyChanged Implemenation public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } #endregion #region IDataErrorInfo Implementation public string Error { get { return null; } } public string this[string columnName] { get { string errorMessage = string.Empty; if (Validate) { switch (columnName) { case "Text1": if (Text1 == null) errorMessage = "Text1 is mandatory."; else if (Text1.Trim() == string.Empty) errorMessage = "Text1 is not valid."; break; case "Text2": if (Text2 == null) errorMessage = "Text2 is mandatory."; else if (Text2.Trim() == string.Empty) errorMessage = "Text2 is not valid."; break; } } return errorMessage; } } #endregion } } 
+10
source share

All Articles