I have a question about how to best perform the validation in the setup below.
I have a small WPF-based UI (using the WAF framework). This particular dialog contains a DecimalUpDown control (this is from the WPF extended toolkit) in which the user may modify the value by using the up/down arrows or typing or pasting.
The user should not be allowed to continue (the Next button should be disabled) until a valid number (format and range) is supplied. The user should also be aware that it is this field's value from preventing them to continue. How do I perform this validation?
I have a pretty simple View Model -- it contains a float FooValue property (bound to the up/down control) and implements an bool IsValid() which the parent container binds to (for the Next button's enabled state).
I notice some other web sites suggest that I should throw an exception in the setter (e.g. http://www.codeproject.com/Articles/15239/Validation-in-Windows-Presentation-Foundation). It doesn't really make sense here because my property is a float. Should that instead bind to the "Text" value of the numeric up/down and do the parsing (and throwing the exception) at the View Model level?
On waf.codeplex.com there is actually an example that shows how to do data input validations - http://www.codeplex.com/Download?ProjectName=waf&DownloadId=282750 . It is using the BookLibrary sample app which is included in the framework source code.
Basically you will be using data annotations on your properties and the ValidatesOnDataErrors=true attribute on your XAML elements.
Related
I am using WPF, MVVM-Light.
In my UI I have a textbox, and I want to prevent the user from typing certain characters in the textbox.
I know if we use code-behind I could handle the key down keyPress events, can I achieve it through MVVM?
Can we use some behaviors or some interactivity triggers?
Using code-behind is perfectly OK with MVVM providing the code-behind is related to your View only.
So if you have some view-specific logic that says "User can only type numbers in this box", then it's perfectly OK to write a KeyPress event for the TextBox that only allows numeric keys to be processed. You could even throw this into a UserControl so it can be reusable.
However if your allowed character logic is based on application logic, such as "User can only use the characters defined in the app.config file for this string value", then you'd be better off validating that in the ViewModel.
Also note that restriction is different from validation.
If you want to validate a user's entry, then I would do so using IDataErrorInfo from the ViewModel layer, and possibly a binding with a mode of UpdateSourceTrigger=PropertyChanged so the validation is checked after every key press.
If you want to restrict what characters can be typed into a TextBox, then I would probably do that from the View layer in the code behind, as that is a functionality of the View.
Yes, to filter input the MVVM way, I would suggest either using a custom control (such as a masked TextBox control) or a Behavior.
I was recently looking for a good masked TextBox and there is a free one out there from Xceed which you can find here. I can't speak to this one, as I haven't used it, but I've been happy with other Xceed components I've used in the past.
However I didn't want to go third party and include a bunch of controls I didn't need, so I ended up creating a behavior that simply attaches to the TextBox and filters the input based on a FilterType. The behavior is pretty easy to create, and you simply use the PreviewTextInput event to filter out characters that you don't want.
This SO Answer has a number of suggestions and links to how to filter/mask the input and if you're not familiar with creating Attached Behaviors, this example shows how to create an Attached Behavior for a Masked Text Box.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
So I'm fairly new to MVVM and I have been struggling with a few issues regarding user input validation. WPF has some built-in features that seem to work like "magic", and generally, I know "magic" is not good.
For Example: If you bind a TextBox to a Property that has a type of double and the user enters "hello" into that TextBox, WPF automatically displays a red border around the TextBox notifying the user that the input is invalid.
This is all well and good, but it does seem like "magic". I was told by an experienced developer that WPF and app builders that are similar want to have too much control. He said that in web development the View would not know what type the Property is. Which makes sense to me. So this leads me to my general question - Should a WPF View understand property types? - If instead I declared the Property type as a string I could then have complete control over the view. Instead of having to work around WPF's "smart" TextBox "magic".
An alternative way to phrase my question is - Should Property types be declared in the Model or ViewModel?
I understand that if you declare the Property type in the Model as a double and as a string in the ViewModel it must be parsed in the Model. In most examples of MVVM applications I have looked at, the Property types are similar across the entire application, but I think that a "dumb" view that doesn't understand what it is working with would be much better.
Back to my example: If the Property were declared as a String you could completely control the format necessary for input and prevent invalid input all-together. This seems like a much better solution than trusting the WPF TextBox.
Yes, I think that feature of WPF is "that nice" :)
WPF has two layers: a data layer and a UI layer.
The data layer contains your data. If you have a number in your data, it should be of a numeric data type, not a string data type.
The UI layer (XAML) is only meant to provide a user-friendly interface for the data so that users can easily interact with the data layer. For example, if you have a data layer containing a numeric value and you want the user to be able to edit that value, you might choose to display your number using a TextBox.
If you force your data layer to use a string instead of a number just because the UI layer is using a TextBox to display the data, then you are letting the UI control your application, which is not how WPF should work. In addition, blending the two layers together like this makes it much harder to maintain in the future. For example, what happens if you decide to change the TextBox to a NumericUpDown UI control? Now you have to go modify your data layer to make a UI change.
In regards to your particular example, when you bind a TextBox to a double and type in a string like "hello", what actually occurs is that WPF tries to set your double value to a string value, and that throws an exception.
That exception is what causes the red border to appear around the TextBox and an error message to display, not any special handling. You could just as easily throw an exception in the setter for your double property, and the same thing would occur.
I wouldn't really call that "magic", just exception handling :)
But to avoid having to throw exceptions anytime you want to validate input, WPF provides the IDataErrorInfo interface which you can use to validate your property without throwing exceptions. The UI will react to errors raised with this interface the same way it would react to Exceptions.
Yes it should.
Karl Shifflett has a great article about it. Input Validation – UI Exceptions & Model Validation Errors
The solution is to detect invalid input. Data binding pipeline will throw exception when user input invalid data type. When it happens handle it on View then add error messages on ViewModel so that you could use it when needed.
WPF by default swallow that data binding exception, but you could add a handler on Loaded event in your View class.
_errorEventRoutedEventHandler = new RoutedEventHandler(ExceptionValidationErrorHandler);
this.AddHandler(System.Windows.Controls.Validation.ErrorEvent, _errorEventRoutedEventHandler, true);
Implement the handler
private void ExceptionValidationErrorHandler(object sender, RoutedEventArgs e)
{
// Add logic to handle this invalid data type exception.
// Add error messages to viewmodel, show notification dialog, etc
...
}
Set these properties on XAML binding NotifyOnValidationError, ValidatesOnDataErrors, ValidatesOnExceptions to true.
Text="{Binding UnitPrice, StringFormat=c, NotifyOnValidationError=True, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}"
That's it.
Since you´re using a strong typed language, you're going to need validation sooner or later. I'm not sure what you would want to achieve by not using a form of validation that is already at hand. Don't forget that you can modify your view to do what ever you want when an invalid input is given. If you don't want any exceptions thrown (as explained by #Rachel), using a string property will likely prevent them.
Declaration
Properties connected to your database are declared in the Model. Properties you need to transform the Model into something userfriendly, are declared in the ViewModel. For example, we have a value (valueA) that is stored in the database. valueA is calculated by using two inputfields the user has available (valueB and valueC). In this case valueA is declared in your Model, but valueB and valueC are only declared in your ViewModel, since they don't need to be stored in the database. (Technically all three are available in your ViewModel but only valueA is declared in your Model)
The way I understand it:
Model Has properties that are stored in the database
ViewModel Converts the Model to something a user can handle (and vice versa).
View Is more or less the 'input area for your ViewModel' in which the user is aided by the use of graphics.
I have a user control which datacontext is set to a view model. The user control contains some textblocks and textboxes which are bind to view model's properties. I would like to do a small animation when a view model's property's value changes but I can't seem to find a way to do this in Silverlight.
In WPF we can use properties like NotifyOnTargetUpdated and Binding.TargetUpdated to capture the change but they seem to be missing from Silverlight. In my case the animation isn't based on the property's value, meaning I don't want to start the animation when some property's value is for example 5. Instead the animation should start every time the property's value is changed (to highlight the changed content for the user).
Here's the answer on how to do this in WPF: Animate WPF Text when binding updates, how?
But how can I do the same with Silverlight 4?
you should be able to get this done using the new trigger stuff included in Expression Blend 4. There's a whole bunch of ne behaviors/triggers etc. that let you react to changes in the ViewModel, for instance.
From the Expression Blend feature page:
New Behaviors
Expression Blend includes the new TranslateZoomRotateBehavior multi-touch Behavior, and a PanningItems control that you can use to scroll between items by using touch. Expression Blend also has a new trigger that responds to a frame change or the pausing or completion of a SketchFlow animation, called the SketchFlowAnimationTrigger. Expression Blend has new sets of Behaviors for dragging items between list boxes, for modifying menu navigation, and for preserving screen states, such as SetDataStoreValueAction and DataStoreChangedTrigger.
An exciting enhancement has been made to the FluidMoveBehavior: if you apply it to different views of the same data item, when the item moves from one view to another (for example, from a list view to a details view), it fluidly animates the transition between the two views.
New Behaviors for use with applications that use the Model-View-ViewModel pattern include the following: CallMethodAction, InvokeCommandAction, and DataStateBehavior. You can use these Behaviors to invoke behavior on your ViewModels, or to respond to changes to their properties.
Conditional Behaviors and the data store
You can now build conditional logic into your prototypes and production applications without the need to write code. In fact any action can be associated with a set of conditions that must be met in order to execute the action. The new data store feature enables application variables, such as the current user's role, for example, can be read from and written to so that, effectively, different parts of your application can communicate via this shared state.
New behavior components introduced as part of this feature include the conditions editor that appears in the Properties panel for every action, a SetDataStoreValueAction action that allows you to manipulate values in your data store, and a DataStoreChangedTrigger trigger that fires whenever a chosen property inside the data store is changed.
http://www.microsoft.com/expression/products/Blend_Features.aspx
Cheers, Alex
I'm trying figure out the best way to validate user input and I've been looking at ValidationRule and IDataErrorInfo. I have a VM and a model and I want to ensure a user does not enter alpha char's into multiple textbox's bound to doubles (or ints).
I'm running into 3 issues
1) When I use the ValidationRule the method returns a 'ValidationResult' but where does that go? Is it stored as property some where?
2) If I user IDataErrorInfo and enter some alpha char's it is never called (it is if numbers are entered) Is that expected? *
*(I thought maybe a value converter might help here but I feel like I'm mixing together two separate concepts)
3) Really what I want to do is do a validation at the end when a user clicks 'Save' and check all the values. So maybe using these two methods aren't what i need as per 1838300. Is that correct, these really are only for 'on the fly' validation?
My thought on point 3 was if the result of the ValidationRule was store somewhere I could check that for each control or where ever it is stored. Or if IDataErrorInfo was called I could manually store some Boolean for each control and check those.
Any thoughts or ideas?
Thanks!
There are a couple of things, you need to know:
When the type of the dependencyproperty is not the same as the underlying value - an automatic conversion is tried if no valueconverter is present.
This is all part of the normal binding engine. So, since your textbox input doesn't convert well to ints/doubles with alpha chars, an exception is thrown and will be continually thrown until you correct the value of the dependency property (here the TextBox's Text property) - the property setter of the underlying dataobject is never reached now.
You can verify this behaviour if you look in your output window for exceptions when you alter the text in the textbox. See this article to see how to properly implement Validation and IDataErrorInfo: link.
You might be interested in the BookLibrary sample application of the WPF Application Framework (WAF). It shows how to use validation in WPF and how to control the Save button when validation errors exists.
I'm looking at developing a simple validation framework for WPF (the IDataErrorInfo method doesn't provide enough info for my needs), and am wondering if there is a way to be notified when a Property is going to validate? Please note that I need to know any time it is going to attempt validation rather than only when there is an error (so NotifyOnValidationError doesn't cut it)
Alternatively, my ultimate goal is simply to package more information than just an error string into my validations (How critical is the error, links for more info, etc.) while still allowing the validation to be driven by the data object (IDataErrorInfo style). If anyone can point me to a method for doing that then I'll be perfectly happy as well. :)
The problem you are going to run into is that WPF databinding and validation are tied to the IDataErrorInfo interface. The bindings check for validation based on the UpdateSourceTrigger property of the binding. So if your binding has "UpdateSourceTrigger=PropertyChanged" then everytime the property changes it calls the item["MyProperty"] which is where you would return information as to whether of not your property is valid. If it's set to "LostFocus" then it checks whenever the control loses focus. The binding also requires the "ValidatesOnDataErrors=True" in order for it to force validation on your bound entity.
I think your best bet would be to create a class that implements IDataErrorInfo and then supply more detailed information based on the severity of the error.
You need to look into inheriting from ValidationRule and then adding the new rule to all you binding objects.