WPF How to access the ValidationResult object in the relevant control? - c#

I want to use the ValidationResult object to send information back to the validated field on my form to reformat the data as necessary, for example:
User enters (123)-456-7890 for the phone number, but in our database all phone numbers are of the format 123.456.7890. The ValidationResult object is created with the args (True, "Reformat") and then the logic of the textbox reformats the String into the proper format. Alternatively, I would be okay accessing the validated field's DP's from within the ValidationRule in order to accomplish the same sort of thing.
How could I do this?

This does not sound like a very good idea to me, since you have a binding to a property anyway i would suggest that reformatting logic is applied in the setter of said property. (The binding engine should get the value afterwards in .NET 4 so this fromatting should even be reflected in the control as well)
Alternatively you can use the Converter layer to accomplish the formatting.

Related

Binding double to Textbox with validation in windows store apps

I am using prism for windows 8 the BindableBase class to validate the properties, till now I can bind the string properties and validate them with custom validator.
Now I want to bind the double value directly to the view with two way binding.the problem is when user enters any alphabetical character then the setter of that double property doesn't gets fire cause its not a double value and might fires a conversion exception but because of that I cant validate my property.
may I go for the converter ?, but how can I raise validation exception and make the property invalid in converter
Does anyone know how to do this?
Two way binding a double does indeed give some issues in Windows Store apps (input validation, localization, ...). What I usually do is have another property that represents this double as a string and bind the string value. You can also add validation on this string property and check if it does parse to a double with double.TryParse().
Hopefully a better solution for Windoew 10 UWP will be announced in the near future to prevent the need for this hack.

C# XAML Binding of a default with IValueConverter

I'm looking for a reason why my code isn't doing its job:
In XAML I use:
<TextBox Text="{Binding Path=Txt_8, Converter={StaticResource DefKonverter}, ConverterParameter='UserAlias'}"/>
In C# there are an IValueConverter which giving me a default value when the ConverterParameter='UserAlias'. For ex. the string 'Jettero'. This works well for that point I see in my TextBox the text 'Jettero'.
I saving my record to database, but in the record Txt_8 still NULL ! (Other fields are saved well)
Looks like the Binding not updating the record field behind the TextBox.
=========== Update start
CONCLUSION: This is not working because the Binding working in one direction. The Converter good for showing special things what makes your user experince better but not to save it.
=========== Update end
A similar issue backward happens also, In XAML:
<TextBox Text="{Binding Path=Date_1, Converter={StaticResource DefKonverter}, ConverterParameter='\{0:yyyy-MM-dd\}TimeStamp'}"/>
This working as it should in the record behind: when I write in the TextBox the '.' character it 'translates' to the today's date. After I save the record, it contains the date.
But in the TextBox I still see the written '.'.
In this sit the Binding not updating the TextBox over the record.
=========== Update start
CONCLUSION: This is not working well because the Binding working in one direction. The Converter good for change the data in that shape how you wanna store.
What is still not answered: when I convert '.' into the present date, it is not showing that - now I see the reason. BUT in the Converter if I'm using a Modal window to somehow extend the data what I wrote in (finding a full text for a keyword), that extended information SHOWS UP in my TextBox beside to store of it.
=========== Update end
I don't know what I miss... I checked lot of using of the default and IValueConverter solutions, but this simple sit never came up. Can anyone help?
I think you might be expecting behaviour from a value converter for which it wasn't designed. What is happening is:
On rendering the textbox, the binding reads a value, let's say null, from your property Txt_8, passes that to the converter, which gives it the value to render, in your example 'Jettero'. This means that the visual representation of your null is Jettero. This isn't meant to (and won't) consequently replace your null with 'Jettero' because, according to the binding engine, it has successfully loaded the value from the source and returned it to the target.
The ConvertBack method of the value converter is supposed to cater for the scenario where the value is changed on the UI and needs to be converted back for storage.
Moral of the story: don't use a value converter for specifying a "default" value for the binding. If your property needs a default value, assign it that in your constructor or initializer. If you want your property value to change itself as it is assigned a value, implement it there, instead of in the converter.
For instance, you can define a Date property like this instead of using a converter:
// disclaimer: untested pseudo-code
private DateTime? _dateTimeField;
public string SomeDateProperty
{
get { return _dateTimeField.ToString('dd-MM-yyyy'); }
set
{
if (value == '.')
value = DateTime.Today.ToString();
_dateTimeField = DateTime.Parse(value);
}
}

PoCo validation on Textbox for Integer DataType

I am developing a WPF application in which i am using a textbox that is bind to an int field of my POCO entity, when i clear the textbox i want my currentobject to be invalid as this is a non nullable field.
But the thing is when i clear my textbox, it convert to string.empty that can ot be set to an int value, so my int field never gets updated and my object remains Valid.
Kindly suggest some logical solution to this.
One approach is to bind to a string value instead (probably added to a view model if you don't want to pollute your model), and then in the setter for the string property, convert the string to an integer to store on your int property.
As i see it, you should not be able to set an 'empty' value to an int control.
Maybe you could use the IntegerUpDown control in the Extended WPF Toolkit which allows you to provide a watermark to show text in place of a NULL Value or set a default value, which could be 0.
It also has button spinners, which can be hidden if needed.
i copied my answer from here. i hope it helps you too.
if your viewmodel has an Property of type int, then your binding just
works if your view got input which is convertable to int. otherwise
your viewmodel will never be informed. there are 2 ways now:
first: you make sure that your view just can take numeric input (with
your numeric textbox) and the viewmodel property can be int.
or second: your viewmodel property type is typeof string and you use
IDataErrorInfo to let the view know when the input is not numeric.
By default WPF should display the ErrorTemplate when a validation error occurs, and this includes validation errors caused by invalid casts, such as trying to store a string field in an int. The default ErrorTemplate for a TextBox is a red border, and for most users this is an indication that something is incorrect and the changes will not get saved.
If you want something more than that, you could try using an IValueConverter in your binding which attempts to cast the value into a int, and will return 0 (or some invalid value) if it fails so your object will get updated with something no matter what the user enters.

Caliburn Micro: Disable button on form validation error

I have a form with a textbox bound to an integer, and a button. Now, when the value of the textbox is invalid, I want to immediately disable the button.
Normally, one would put a Can() method in the VM, and trigger a NotifyOfPropertyChange in the property's setter. However, if the user inputs a non numeric value for example, the textbox is invalid, but the property setter is never called, so I can't notify/disable the button.
So, how do I disable the button, when the user inputs an invalid value that doesn't cause the property setter to get called? My knowledge of CM is limited as I've just started out.
I've found the best approach to this problem is to make the property a string instead and do the necessary string to integer conversion in your property setter. If the conversion is invalid, then you could reset the TextBox value to a default value. This way your property setter will always get fired.
If your model has an integer property, then it makes sense to place the string version on the view model, as this is only really related to the UI, rather than business logic.
If you don't wish the user to be able to input non digit characters, then you can use a masked text box, such as the one included in the Extended WPF Toolkit, or in a third party control suite such as those offered by Telerik or Infragistics.
I'd use a MaskedTextBox instead and set the mask to integer only.

Two-way data binding objects

I used an application recently that was awe-inspiring. All the forms inherited from their own classes and a 'form' came with an amazing amount of functionality and looked the nuts.
What I'm interested in is this 'feature' of the form. This was a C# WinForms project and blew me away.
The forms were bound to objects that the group had written to support two-way data binding (to an extent). The way they behaved was pretty simple:
The data input forms all had controls that inherited from textbox and these were bound to properties of an object, Entering data immediately validated it and the box was a light pink if validation failed and a light green if it passed. If the box ever turns blue this actually means the value in the database the form is bound to has changed and your changes to the controls were immediately saved when valid values entered. It was the case that sometimes a section of controls had to be filled before a save occured. But it was all automatic. You could stop at any point and come back later and continue without actually saving yourself.
And like I say if someone else is editing the same record values they change caused your textboxes to become blue and you knew you needed to reload the screen to see up to date information.
All of this came from using their own form class they had written and their own textbox controls bound to an objects property.
I'm mainly wondering how the hell did the object figure out the value had been changed by someone else. It surely isn't polling the database. This system was amazing. The brilliance didn't stop there.
For simplicity. How might I create an object or collection of objects to mimic the bahaviour. I'm not going to but I can't even see how.
Thanks
I'm pretty sure that anything involving other people's changes would have needed to hit the database. For two-way binding, all you really need is change notification - i.e. INotifyPropertyChanged (or a FooChanged event for every Foo property). This is all abstracted into TypeDescriptor - i.e. any binding that uses the regular PropertyDescriptor implementation (which it should) will know about notifications via SupportsChangeEvents, AddValueChanged and RemoveValueChanged.
For validation - IDataErrorInfo is your friend; by implementing this, you can volunteer validation information (which is used and displayed by several controls, such as DataGridView). i.e.
IDataErrorInfo dei = obj as IDataErrorInfo;
if(dei != null) { // supports validation
string err = dei["PropName"]; // or .Error for overall status
bool clean = string.IsNullOrEmpty(err);
}
Note that an alternative approach would be to have a Color property on the data aobject, and bind that directly to the textbox etc.

Categories