Reputation: 3641
I read most of the articles and i was happy that i could use attributes (with IDataErrorInfo) for validaton. That was great. But i wasted hours and still no good solution in order to display custom messages in cases that IDataErrorInfo isnt fired because casting has failed. No matter what error appears and it makes no sense and i want to translate it.
Should i apply a custom convertor or a custom validation rule ?
Upvotes: 2
Views: 2797
Reputation: 2944
You might want to check out this blog post: http://wpfglue.wordpress.com/2012/05/06/checking-property-types-automatically/
It contains examples on how to set up ValidationRules so that type conversion errors are caught before they happen, and are translated into meaningful and localized error messages. IDataErrorInfo won't help you here, unless you really want to wrap all your properties into strings as suggested, which I wouldn't like to do. The reason is that IDataErrorInfo only is queried after setting the property on the bound object succeeded, which won't happen if the types don't match.
Upvotes: 1
Reputation: 22445
i use string properties in my viewmodels, so i could handle every input with idataerrorinfo. of course i have to parse my string properties to the right type when calling a service or put the value to my model.
another way would be to forbid input in your view. eg. with numeric only textbox.
or using Behaviors(Blend Sdk) like:
<TextBox Text="{Binding MyDecimalProperty}">
<i:Interaction.Behaviors>
<Behaviors:TextBoxInputBehavior InputMode="DecimalInput"/>
</i:Interaction.Behaviors>
</TextBox>
.cs
public class TextBoxInputBehavior : Behavior<TextBox>
{
const NumberStyles validNumberStyles = NumberStyles.AllowDecimalPoint |
NumberStyles.AllowThousands |
NumberStyles.AllowLeadingSign;
public TextBoxInputBehavior()
{
this.InputMode = TextBoxInputMode.None;
}
public TextBoxInputMode InputMode { get; set; }
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.PreviewTextInput += AssociatedObjectPreviewTextInput;
AssociatedObject.PreviewKeyDown += AssociatedObjectPreviewKeyDown;
DataObject.AddPastingHandler(AssociatedObject, Pasting);
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.PreviewTextInput -= AssociatedObjectPreviewTextInput;
AssociatedObject.PreviewKeyDown -= AssociatedObjectPreviewKeyDown;
DataObject.RemovePastingHandler(AssociatedObject, Pasting);
}
private void Pasting(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(string)))
{
var pastedText = (string)e.DataObject.GetData(typeof(string));
if (!this.IsValidInput(this.GetText(pastedText)))
{
System.Media.SystemSounds.Beep.Play();
e.CancelCommand();
}
}
else
{
System.Media.SystemSounds.Beep.Play();
e.CancelCommand();
}
}
private void AssociatedObjectPreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
{
if (!this.IsValidInput(this.GetText(" ")))
{
System.Media.SystemSounds.Beep.Play();
e.Handled = true;
}
}
}
private void AssociatedObjectPreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (!this.IsValidInput(this.GetText(e.Text)))
{
System.Media.SystemSounds.Beep.Play();
e.Handled = true;
}
}
private string GetText(string input)
{
var txt = this.AssociatedObject;
var realtext = txt.Text.Remove(txt.SelectionStart, txt.SelectionLength);
var newtext = realtext.Insert(txt.CaretIndex, input);
return newtext;
}
private bool IsValidInput(string input)
{
switch (InputMode)
{
case TextBoxInputMode.None:
return true;
case TextBoxInputMode.DigitInput:
return CheckIsDigit(input);
case TextBoxInputMode.DecimalInput:
if (input.Contains("-"))
if (input.IndexOf("-") == 0 && input.LastIndexOf("-")==0)
return true;
else
return false;
if (input.ToCharArray().Where(x => x == ',').Count() > 1)
return false;
decimal d;
return decimal.TryParse(input,validNumberStyles,CultureInfo.CurrentCulture, out d);
default: throw new ArgumentException("Unknown TextBoxInputMode");
}
return true;
}
private bool CheckIsDigit(string wert)
{
return wert.ToCharArray().All(Char.IsDigit);
}
}
public enum TextBoxInputMode
{
None,
DecimalInput,
DigitInput
}
Upvotes: 0
Reputation: 81333
In case you want to customize the message, only way to do is implementing your own Validation rule
. Refer to this link here for the code Custom Validation.
Upvotes: 0
Reputation: 5885
I don't know how you do Validation right now. But consider using the IDataErrorInfo Interface.
You can find an example here
http://codeblitz.wordpress.com/2009/05/08/wpf-validation-made-easy-with-idataerrorinfo/
Upvotes: 0