Implement Validation for Wpf Textboxes

How to successfully implement WPF textbox validation?

Using what you posted, it works fine for me, it produces the red "!" above the textbox. However, I DID remember to set my DataContext, ie.

public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}

Without this, it won't work.

How to validate user input in a textbox with updateSourceTrigger=Explicit with xaml:C#?

Finally, I used :

private void txtBox_mailSender_LostFocus(object sender, RoutedEventArgs e)
{
txtBox_mailSender.GetBindingExpression(TextBox.TextProperty).ValidateWithoutUpdate();

}

and in my textbox

UpdateSourceTrigger="Explicit"

without specifying the binding mode.

With ValidateWithoutUpdate(), the validation rules are performed without updating the source as I wanted because I have a Validate Button in which I update the source with

txtBox_mailSender.GetBindingExpression(TextBox.TextProperty).UpdateSource();

I found this answer thanks to RolandJS and because I took a look at all the possible expressions after GetBindingExpression(TextBox.TextProperty)..

Thank you to everyone for your help !
Have a good day! Mine will be better now :-)

C# WPF very simple TextBox Validation

TextBox is supposed to be bound to property Alter. For binding to work you need to set DataContext - an object with Alter property, e.g.

public class Test
{
public string Alter { get; set; }
}

and

public MainWindow()
{
InitializeComponent();
DataContext = new Test();
}

then if you enter negative number, there will be red border around TextBox

WPF TextBox Validation

This really depends on your implementation of IDataErrorInfo. If you base it around a Dictionary of error messages you can control when validation runs that adds to that list. You would normally want to do that from your property setters (like whenever you call PropertyChange), here calling CheckValidationState:

    public string this[string columnName]
{
get
{
return ValidateProperty(columnName);
}
}

public Dictionary<string, string> Errors { get; private set; }

protected void SetError(string propertyName, string errorMessage)
{
Debug.Assert(!String.IsNullOrEmpty(propertyName), "propertyName is null or empty.");
if (String.IsNullOrEmpty(propertyName))
return;

if (!String.IsNullOrEmpty(errorMessage))
{
if (Errors.ContainsKey(propertyName))
Errors[propertyName] = errorMessage;
else
Errors.Add(propertyName, errorMessage);
}
else if (Errors.ContainsKey(propertyName))
Errors.Remove(propertyName);

NotifyPropertyChanged("Errors");
NotifyPropertyChanged("Error");
NotifyPropertyChanged("Item[]");
}

protected virtual string ValidateProperty(string propertyName)
{
return Errors.ContainsKey(propertyName) ? Errors[propertyName] : null;
}

protected virtual bool CheckValidationState<T>(string propertyName, T proposedValue)
{
// your validation logic here
}

You can then also include a method that validates all of your properties (like during a save):

    protected bool Validate()
{
if (Errors.Count > 0)
return false;

bool result = true;
foreach (PropertyInfo propertyInfo in GetType().GetProperties())
{
if (!CheckValidationState(propertyInfo.Name, propertyInfo.GetValue(this, null)))
result = false;
NotifyPropertyChanged(propertyInfo.Name);
}
return result;
}

UPDATE:

I would recommend putting the above code into a base ViewModel class so you can reuse it. You could then create a derived class like this:

public class SampleViewModel : ViewModelBase
{
private string _firstName;

public SampleViewModel()
{
Save = new DelegateCommand<object>(SaveExecuted);
}

public DelegateCommand<object> Save { get; private set; }

public string FirstName
{
get { return _firstName; }
set
{
if (_firstName == value)
return;

CheckValidationState("FirstName", value);

_firstName = value;
NotifyPropertyChanged("FirstName");
}
}

public void SaveExecuted(object obj)
{
bool isValid = Validate();
MessageBox.Show(isValid ? "Saved" : "Validation Error. Save canceled"); // TODO: do something appropriate to your app here
}

protected override bool CheckValidationState<T>(string propertyName, T proposedValue)
{
// your validation logic here
if (propertyName == "FirstName")
{
if (String.IsNullOrEmpty(proposedValue as String))
{
SetError(propertyName, "First Name is required.");
return false;
}
else if (proposedValue.Equals("John"))
{
SetError(propertyName, "\"John\" is not an allowed name.");
return false;
}
else
{
SetError(propertyName, String.Empty); // clear the error
return true;
}
}
return true;
}
}

In this case I'm using a DelegateCommand to trigger the save operation but it could be anything that makes a method call to do the saving. This setup allows for the initial empty state to show up as valid in the UI but either a change or a call to Save updates the validation state. You can also get a lot more general and more complicated in the way you actually do the validation so it doesn't all end up in one method (here with some assumptions about the type) but this is simplified to make it easier to start with.

WPF - Custom ErrorTemplate for all TextBoxes in App

You need to define new Style for TextBox inside a "Resourse" tag of textbox's container. This style will be implemented for each textbox inside container.

Example:

<StackPanel>
<StackPanel.Resources>
<Style TargetType=TextBox>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<AdornedElementPlaceholder x:Name="textBox"/>
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ErrorContent}" Foreground="Red"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources
<TextBox/>
<TextBox/>
<TextBox/>
</StackPanel>


Related Topics



Leave a reply



Submit