I am using MVC\MVVM and WPF. I have a form that is bound to a model and a controller that is catching the PropertyChanged events and evaluating business rules and validations.
Well, I want to pop-up a message when a validation is false telling the user what is wrong and how to fix it. But I'm not sure the "correct" way from the controller. I'd like to throw an exception that can be caught by the view but I can't figure out how.
I've tried Dispatcher.Invoke() but that just got me an unhandled exception at the application level.
How do I trap exceptions that are generated from the PropertyChanged event handler in the Controller?
EDIT: Specifically I have a combobox that has a list of discounts in it. I can't allow an inappropriate selection, but I have to notify the user why the selection is inappropriate. This is not as obvious as a textbox that has integers in it. I need to tell the user the date the customer filled out a survey. They can't use that discount twice. I don't want to exclude the survey discount from the list since that would just look like an error to the user. I need to show them the discount and tell them the customer has used that discount and cannot use it again.
EDIT 2: I have looked over the ValidationRule class and since I have to use a database lookup I don't see how I'm going to keep everything in the Model and still have the business rules in the Controller. I've looked at IDataErrorInfo but that requires me to wrap my Model in my Controller and bind to the Controller instead, but only for one field. I think the best course of action in this case is to have the Controller call a method on the View and pop-up a message.
You are walking down the wrong path.
A good way to handle validation in MVVM is by implementing IDataErrorInfo and setting ValidatesOnDataErrors to true on your bindings. You will also almost certainly want to enable ValidatesOnExceptions for completeness, and NotifyOnValidationError so that the binding engine triggers the Validation.Error attached event on the control that you have bound the property to.
For more details, see the Validation section on the MSDN documentation for data binding in WPF.
Some tips:
.NET 4.5 introduces INotifyDataErrorInfo and the corresponding ValidatesOnNotifyDataErrors binding property that provide beefed-up validation functionality in comparison to IDataErrorInfo; you might want to look into that.
You do not need to actually do anything meaningful inside IDataErrorInfo.Error because it is used by the Windows Forms infrastructure and is ignored in WPF. You can even have the getter throw NotImplementedException.
There is good reading material illustrating this approach, complete with examples and code, here and here.
Update: clarification and example code
This validation model does not involve implementing a ValidationRule yourself at all; your models (i.e. the binding sources) simply need to implement one of the two interfaces. How to implement the interface is entirely up to you; in a past project I implemented basic async validation with
public interface IDelegatedValidation : IDataErrorInfo
{
/// <summary>
/// Occurs when validation is to be performed.
/// </summary>
event EventHandler<DelegatedValidationEventArgs> ValidationRequested;
}
public class DelegatedValidationEventArgs : EventArgs
{
public DelegatedValidationEventArgs(string propertyName)
{
this.PropertyName = propertyName;
}
public string PropertyName { get; private set; }
public bool Handled { get; set; }
public string ValidationError { get; set; }
}
The model implements IDelegatedValidation by exposing an event and with
string IDataErrorInfo.this[string columnName]
{
get { return this.GetValidationError(columnName); }
}
private string GetValidationError(string propertyName)
{
var args = new DelegatedValidationEventArgs(propertyName);
this.OnValidationRequested(args);
return args.ValidationError;
}
protected virtual void OnValidationRequested(DelegatedValidationEventArgs args)
{
var handler = this.ValidationRequested;
if (handler == null) {
return;
}
foreach (EventHandler<DelegatedValidationEventArgs> target in handler.GetInvocationList()) {
target.Invoke(this, args);
if (args.Handled) {
break;
}
}
}
So the workflow goes like this:
When the model is about to be wrapped by a viewmodel, some appropriate entity that can perform the validation subscribes to its ValidationRequested event.
The view binds to the model; at some point validation is triggered.
The model calls GetValidationError.
Event handlers get invoked one by one; the first handler that produces a validation error sets args.ValidationError and args.Handled to true so that the chain is stopped.
The validation error is returned to the view.
There is an added twist in that if the viewmodel needs to know whether its model is valid or not (e.g. to enable/disable a "save" command) it needs to also tap into this process.
There's really nothing that you cannot do with IDataErrorInfo / INotifyDataErrorInfo because how you implement them is entirely up to you. Definitely have a look at the Silverlight version of the latter's documentation for more examples; there is also a lot of helpful material like this on the internet.
Related
In a MVP Winforms application I'm doing initial validations in the View using following method. (Though business logic related validation done in the Model). In Form's constructor using a foreach loop I'm delegating all TextBoxe's Validating event to this handler.
//Validates all text boxes in the form
private void textBox_Validating(object sender, CancelEventArgs e)
{
TextBox currenttb = (TextBox)sender;
{
if (string.IsNullOrWhiteSpace(currenttb.Text))
{
currenttb.BackColor = Color.OrangeRed;
currenttb.Name.Substring(3)));
}
else
{
e.Cancel = false;
currenttb.BackColor = Color.White;
}
}
}
public Form()
{
InitializeComponent();
//In form's constructor, following eventhanderlrs are hooked up to validating events of controllers,
//there for one controller type shares a single handler
foreach (TextBox tb in this.Controls.OfType<TextBox>().Where(x => x.CausesValidation))
{
tb.Validating += textBox_Validating;
}
}
Without repeating this code in every View. it'd better if I could keep it in a one place. So could you show me a better way to keep this centrally making it available to all Views?
NOTE: My View is not aware of the Model and Presenter. Presenter's ShowView() method is invoked to display the View to user. I cant do this validation in Presenter as the presenter access the View through IView's public properties so the validation should take place even before the Presenter act on those properties.
EDIT:
For ex. IView has properties like
void int ID {get; set;}
void string Name {get; set;}
etc.
If the presenter is supposed to do the validate like
private void ValidateID()
{
try
{
Validate (_View.ID);
}
catch {}
}
So what would happened if the user had kept the txtID.text empty? This would lead to an exception in the view when it tries to convert null value to int.
Please note that this explanation is totally based on my understanding of the matter and kindly let me know if I've missed anything .
Instead of keeping an int property in the View interface you can keep a string. This way when you get the user's input there would be no way of throwing an exception because there would be no parsing in the code-behind. You would then make the parsing in the Presenter. By doing so you can have a centralized place to validate the input.
The View's job is to only supply the user's input to the Presenter not to validate it.
By following my suggestions if you have to do the same validation on a lot of places you can make a base Presenter class that other Presenters are inheriting from and put the validation there. It would certainly be easier than making a base Form that other forms are inheriting from.
How do I call a function on a user control from a separate view model?
In my scenario, I have a "main" view with a ScoreDisplay UserControl:
<local:ScoreDisplay/>
This control will display the score of n number of players in my game. The main view model is hooked up to a game controller that feeds it the score updates. I need to get these updated scores to the UserControl (and run some animations, non-trivial logic, etc.)
I see a few options:
Create a "Scores" dependency property and bind it to the view models collection of scores. The only problem I see with this approach is that whenever it is modified, I need to go look and see what changed so I can run the appropriate animations. Doing this is certainly possible, but doesn't seem "right".
Have the ViewModel invoke a "UpdateScore" function on the UserControl. The only problem, of course, is that the ViewModel shouldn't know anything about the View and so shouldn't have the reference necessary to do this.
Have the UserControl register for a "ScoreUpdated" event on the view model. This seems like the best option, but I have no idea on how to get the reference to the ViewModel in order to register for the event.
Which option, if any, is the correct approach? If (2) or (3), how can I implement this?
EDIT:
To be clear, the values in the scores collection are changing (the collection itself remains the same). I could put a wrapper around the score int and listen to PropertyChanged, but again, this seems like an overcomplicated approach to a simple problem. If that is the best solution though, please let me know!
EDIT 2:
UpdateScore is a function that (in theory) accepts the index of the updated score and the value to add to that player's score (it could accept the whole score). It then causes the player's peg to move along a cribbage track to its new position.
It gets called whenever a player gets points (this is a Cribbage game, so this happens a lot). The view model is attached to a game controller that raises an event to notify the VM that a player has been awarded points. The view model basically just needs to pass this information to ScoreDisplay for display/animation etc.
In this case we can apply the Mediator pattern, if this is succeed, it will not need the event.
There are several embodiments of the Mediator pattern, but I like the most the implementation by XAML Guy, it is simple and clear - The Mediator Pattern.
Implementation code
public static class Mediator
{
static IDictionary<string, List<Action<object>>> pl_dict = new Dictionary<string, List<Action<object>>>();
static public void Register(string token, Action<object> callback)
{
if (!pl_dict.ContainsKey(token))
{
var list = new List<Action<object>>();
list.Add(callback);
pl_dict.Add(token, list);
}
else
{
bool found = false;
foreach (var item in pl_dict[token])
if (item.Method.ToString() == callback.Method.ToString())
found = true;
if (!found)
pl_dict[token].Add(callback);
}
}
static public void Unregister(string token, Action<object> callback)
{
if (pl_dict.ContainsKey(token))
{
pl_dict[token].Remove(callback);
}
}
static public void NotifyColleagues(string token, object args)
{
if (pl_dict.ContainsKey(token))
{
foreach (var callback in pl_dict[token])
callback(args);
}
}
}
Communication via a Mediator is carried out as follows:
Mediator.NotifyColleagues("NameOfYourAction", ObjectValue);
In this case, we notify NameOfYourAction that you need to pass the ObjectValue for him. In order to NameOfYourAction successfully received the data, it is necessary to register it in the class or in the ViewModel like this:
private void NameOfYourAction_Mediator(object args)
{
MyViewModel viewModel = args as MyViewModel;
if (viewModel != null)
viewModel.PropertyA = someValue;
}
// Somewhere, may be in constructor of class
Mediator.Register("NameOfYourAction", NameOfYourAction_Mediator);
In your case, the value is passed ScoreData in ViewModel, where which will be changes.
For more example of using pattern Mediator, please see this answer:
One ViewModel for UserControl and Window or separate ViewModels
Anatoliy Nikolaev's answer above is a good one.
As another option I would also suggest looking into the Event Aggregator. This is a great pattern and has many uses. They would both get a reference to the Event Aggregator and then one could publish an event and the other would receive it and could take action. If you enable something like this in your application it becomes trivial for multiple ViewModels to communicate in a completely decoupled way. And as an added bonus testing becomes simple as you can easily mock out your Event Aggregator to supply any data needed.
I found a way to do this:
I made a dependency property of my view model type:
public GameViewModel BaseViewModel
{
get { return (GameViewModel)GetValue(baseViewModelProperty); }
set { SetValue(baseViewModelProperty, value); }
}
public static readonly DependencyProperty baseViewModelProperty =
DependencyProperty.Register("BaseViewModel", typeof(GameViewModel), typeof(ScoreDisplay), new PropertyMetadata(null, RegisterForScoreChange));
and changed my XAML to:
<local:ScoreDisplay BaseViewModel="{Binding}"/>
Then in the PropertyChanged event handler of the dependency property, I was able to wire up my event.
(e.NewValue as GameViewModel).ScoreUpdated += (d as ScoreDisplay).UpdateScore;
I've got a WPF app that's using INotifyPropertyChanged to signal property updates. What I like about it is that it gives you the ability to signal a property change without invoking all of the setter code. This is handy when you've got two linked fields that update each other or when you've got code that saves changes on every setter and you don't want to trigger the save multiple times for what is essentially one change by the user.
However the obvious weakness of this approach is that a mistake in the property name or on which viewmodel you send the notification to will mess you up and only show up and runtime.
I looked into dependency properties but was unable to find anything that lets you do a "soft update": let the UI know that the property has changed but avoid calling all the code that would normally run when a UI causes a change in the viewmodel.
Is there some way I can get a property system that allows soft updates and catches notification problems at compile-time?
If the underlying problem is mistakes in the property name, there are compile-time solutions, like making the "property name" parameter an expression tree instead of a string.
http://michaelsync.net/2009/04/09/silverlightwpf-implementing-propertychanged-with-expression-tree
The Caliburn.Micro library also includes this approach in its PropertyChangedBase class.
I like Foson's solution for "early binding" vis a vis the property names and eliminating the need to keep a string copy of your property name around. This is the core of the implementation I, personally, use:
public virtual string GetName<T>(Expression<Func<T>> expression)
{
return GetMemberName(expression);
}
/// <summary>Abstraction for actually finding the name of the target of the expression</summary>
private static string GetMemberName<T>(Expression<Func<T>> expression)
{
if (expression != null)
{
var myMemberExpression = expression.Body as MemberExpression;
if (myMemberExpression != null && myMemberExpression.Member != null)
{
return myMemberExpression.Member.Name;
}
}
return string.Empty;
}
This code resides in a class called NameResolver, which my ViewModelBase class wraps with
NotifyChange(Expression<Func<T>> expression)
Then client code looks something like:
private int _myBindable;
public int MyBindable { get { return _myBindable; } set { _myBindable = value; NotifyChange(() => MyBindable); }
As to the notion of separating GUI notification from updating underlying stuff, you can invoke those NotifyChange() methods elsewhere than the property setter when whatever happens in your code that should trigger UI update happens. So, GUI sets your property, which triggers some logic, but you don't raise change notification there -- you raise it from wherever, specifically, you want to inform the UI about something.
Looking for guidance on where to place code which is dependent upon changes to a property.
For example, I have a view model which is used to hold state for an applications settings
public SettingsViewModel(ISettingsRepository settings)
{
_settings = settings;
// ...
}
For each change to a settings property we have to persist this change to the repository, and on some properties, other properties are affected, so additional code is required.
I started off just adding this logic to the setter
public ProjectCollection Projects
{
get { return _projects; }
set
{
if (_projects == value) return;
_projects = value;
RaisePropertyChanged("Projects");
// Extra work needed when collection of projects change
_settings.SaveProjects(_projects);
Startable = _projects != null && _projects.Count > 0;
}
}
But then swapped over to wiring up the PropertyChanged event for INotifyPropertyChanged and removed the additional code out of the property setter
public SettingsViewModel(ISettingsRepository settings)
{
_settings = settings;
// ...
PropertyChanged += onPropertyChanged;
}
void onPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "Projects":
_settings.SaveProjects(Projects);
Startable = Projects != null && Projects.Count > 0;
break;
// ...
}
}
public ProjectCollection Projects
{
get { return _projects; }
set
{
if (_projects == value) return;
_projects = value;
RaisePropertyChanged("Projects");
}
}
Having the logic inside the setter means less code to write, less chance of making a mistake wiring up the wrong property name (unit test should pick this up though) and would be slightly faster, although probably insignificant.
Having the logic wired up to an event seems to be a more maintainable approach, so long as the methods are appropriately named it should be easier to follow the code, and means the setter isn't doing other work besides setting the property. I'm guessing it might also provide more flexibility, using the example above, if the requirements changed so that persisting of changes happened from another event e.g. "Save" button click instead property change, then the code should be easier to change.
I appreciate this is a subjective question, but I'm new to the MVVM pattern (although I guess it may hold true for any setter logic?) so am looking for other reasons before I settle on an approach. Thanks!
When deciding what code to put where, remember this: a ViewModel is for presenting the data to the View. It can massage or manipulate the data a little to do so (within reason of course - changing a value to a color could be considered absolutely fine to do). The ViewModel doesn't know anything about the UI, and it doesn't know anything about saving data.
The property setters should be kept as simple as possible, and they should notify if anything relies on them (which mostly will be the case - the VM is used for binding). This means that your second example utilizing the OnPropertyChanged() event handler is a far better option than the first example.
However, it still knows too much for my liking. I would raise events which the Model can subscribe to, and let the Model do the work. The ViewModel should just say "hey, my data has changed, I don't care what you do about it but i've told you so do whatever you like". The Model can then either save instantly, or what till more changes have taken place before persisting the data.
thanks for your attention and time.
I want to implement validations in settter of properties. Here is an issue where your expert help is required please.
I have idea of how I will do validations before setting value. but not getting what to do if passed value is not correct. Just not setting is not a acceptable solution as I want to return an appropriate message to user (in a label in web form). My example code is:
private int id;
public int Id
{
get
{ return id; }
set
{
bool result = IsNumber(value);
if (result==false)
{
// What to do if passed data is not valid ? how to give a appropriate message to user that what is wrong ?
}
id = value;
}
}
A thought was to use return but it is not allowed.
Throwing error looks not good as generally we avoid thorwing custom errors.
Please guide and help me.
thanks in anticipation
haansi
You could consider throwing appropriate exception from property setter. That way it will be clear to the calling party what went wrong, especially assuming you have business rules with respect to setting properties. Of course you do expect the caller to do validations, if still there is a problem, then throwing exception doesn't seem that bad.
"It is valid and acceptable to throw exceptions from a property setter."
Property design guidelines
Best practices: throwing exceptions from properties
What exception to throw from a property setter?
I think you'd better change to another example because:
public int Id
{
get { ... }
set
{
if (!IsNumer(value)) // changes to if (value>5)
{
//the code here will never be executed
id = value;
}
}
}
If the check is only about number (type) then your property can very well handle the type safety. Eg. User wont be able to assign string to a property accepting int.
I would suggest that if Property involves certaing computations, then one should consider using a method instead. In that case, you will option to get some text in return.
One more option is to store all these validation checks in an instance collection (inside the same object). Like.
private List _faileValdations;
//more code
set
{
if (!IsNumber(value))
{
_faileValdations.Add("Invalid value for xxx. Expected... got..");
}
else{
id = value;
}
}
And then, your GUI can read the FailedValidations collection in the end, and display it in a formatted way in some label.
Edit: one more option below.
Sorry i forgot to mention about this before.
You can use an event driven approach also.
You object can expose an event like "ValidationFailed", and all the GUI objects can subscribe to this event. The object will trigger this event in case any validation is failed in the setters.
set {
if (!IsNumber(value))
{
RaiseValidationFailed("some message");
}
else{
id = value;
}
}
"RaiseValidationFailed" can collect the message, wrap it up in some event args and trigger "ValidationFailed" event with the message. Then GUI can react to this.
{I can provide you a full code for this if its not clear}
I would argue that you should rethink your approach to validation. The approach that you are suggesting means that every time a property changes, a message will be generated.
How will these messages be collected, stored and presented? Especially if you decide to use your classes in a website?
What if you want to validate your class at any other time?
What if you want to use the same rules in client side validation?
I can understand the appeal of catching an invalid value as early as possible, but it is a lot easier to validate an entire class in one call such as a Validate() method. This way, you have full control over when the validation logic is run.
I would recommend you read up on the two leading approaches to property validation:
Data Anotations
Fluent Validation for >NET 3.0 and above
Fluent Validation for .NET 2.0
Both Data Annotations and FluentValidation are easy to use and they are able to generate well-tested client side validation on web forms and win forms.
In Data Annotations, the validation is added to the properties using attributes. If you prefer to keep your data classes as clean data transfer objects, Fluent validation involves the creation of easily readable rules in Validator classes.