I am currently developing a UWP application, but I think this question applies to any project type with a UI. I have built a View Model for my UI using the new Microsoft Toolkit MVVM library. It has properties such as:
private bool _isLoginAvailable = true;
public bool IsLoginAvailable
{
get => _isLoginAvailable;
set => SetProperty(ref _isLoginAvailable, value);
}
Furthermore, I have a few business methods that as parameters require up to 5-6 of these properties.
Reading on forums, I saw that it is unadvised to business logic within the view model, therefore, I came up with the following options:
Create a new class for the methods, and use the view model as a parameter: SampleMethod(SampleViewModel vm). Then, if I create an object of this class in the view model, I could use SampleMethod(this). At this point, I don't really see a difference between this option, and including the method within the view model class.
Second option I see is to add each required parameter to the method, and return each parameter as well in a tuple: SampleMethod(var1, var2, var3...) { return (var1, var2, var3...)} This to me seems very cumbersome.
The third option I figured is to use the MVVM Toolkit's messaging feature. In this case, I can set up the constructor of the view model to listen to messages with Messenger.Register<SampleViewModel, Var1Message>(this, (r, m) => r.var1 = m.Value);. Then, the method in a differenct class can send the value in message using Messenger.Send(new Var1Message(message). While this seems to be the best option, as it can be easily implemented together with dependency injection, it quickly becomes very convoluted, as for each property a new sealed class is required, that describes the message.
Is any of these options the best practice, or is there an option that I am not aware of?
If business methods require multiple properties in your VM, then maybe the properties should be in the business object? Are the properties intrinsic to the business rules, or do they only exist in the context of the view?
VM properties can just pass through to the business properties, or quite often you can just directly expose the business object itself in your VM.
Why do you think that its inadvisable to use methods within a ViewModel?
A ViewModel must act as an intermediary between the View, Model and business logic classes or libraries.
Consider using a RelayCommand (implement the property as ICommand type) in your ViewModel, this can be bound to a button click and is used to call a method within your ViewModel that takes the property values and passes them to your business logic.
A typical scenario for a ViewModel may be user input on a form, with your ViewModel properties being bound by the View. The user then clicks a button to submit this data.
I have a question about when to validate inputs on C# form applications.
When taking inputs from a form application, you can run all the validation as you parse in the data from the text fields in the main form class, to then use wherever. For example:
Method 1:
class Car
{
private string registration { set; get; } // NO VALIDATION HERE
}
// in the form class
private void add_Click(object sender, EventArgs e)
{
// get registration
int reg_valid = Validate.registration(txtReg.Text); // VALIDATION IS DONE HERE
if(reg_valid)
{
Car.registration = txtReg.Text;
} else {
// Registration invalid - throw error
}
}
There will be no validation in the actual Car object as it is all done in the form class.
The other way is to validate the input in the actual class it is stored in like:
Method 2:
class Car
{
// out registration
private string registration;
// we can set our registration here and return false if there is an error
bool set_registration(registration)
{
int reg_valid = Validate.registration(registration); // VALIDATION IS DONE HERE
if(reg_valid) {
this.registration = registration;
} else {
return false; // if error
}
return true; // if all goes well
}
}
// in the form class
private void add_Click(object sender, EventArgs e)
{
// get registration
string registration = txtReg.Text; // NO VALIDATION DONE HERE
// we can then store this in our object
if( ! Car.set_registration(registration))
{
// Registration invalid - throw error
}
}
Method 1 seems cleaner, but one of the reasons why we use private attributes is so that we can validate any parsing arguments which is why method 2 seems the better option. Also, using method 2, errors have to be carried up the stack possibly many times, which leads to repeated if statements.
* Please note, this code has not been ran so may contain errors.
Caution : Opinion-based answer !
It depends on the requirements of the Project, its scale, and the time you have (and many other factors of importance like "User Friendly Application" or of no importance like "my own taste would be..")
Due to the wide range of possible cases per individual, the answer cannot be expressed in a general guideline which would fulfill the needs of everyone.
Your question addressed two objects to manipulate :
one Form used as an User Interface where the user can input anything (assumption defined by "the user enter *any* value then click a Button")
a Class Property that is fed with the value (Setter) when it's valid.
You have no time, requirements just tells "Input a value", this is a small task in the Project of no critical importance on a small class used within this Button, and you're very lazy :
=> In Button Click, make a rigid validation with one or two forbidden checks that whip out any non allowed value, and shows a MessageBox depending on the nature of the Error. Only pass a Value to the class and go further when you have a valid value.
.
You have no time, simple requirements, small task of no critical importance but with a class largely used, but you're lazy :
=> Move the validation above in the class then Throw one, two or three generic Exceptions with custom messages. In any UI action using that class, use Try/Catch to capture the exception in the ButtonClick and display a MessageBox without going further in case of captured Exception.
.
You have 5 minutes, simple requirements, small non critical task, important Class role :
=> Like previously but, decide whether another way to show user is more recommended (depending of your target users) like changing the background color of a TextBox after you click a button, displaying the message in a Label, instead of annoying the user with a dialog box...
.
You have 10 minutes, simple requirements, repetitive task, important Class role :
=> Find a way to quickly test a given value and creates a public or friend (static ?) function in your Class that returns the result of a validation attempt, like an UICarValidationEnum Enumeration (* see Edit below) of possible Validation Errors :
a) UICarValidationEnum.Valid
b) .TooLong
c) .NullValue
d) .ForbiddenChars
e) ...
You can then use that validation Function inside and outside your Class. That way, you can handle invalid Setter attempts both before performing the Setter and while performing it, aswell as both using you class along with UI and without. The drawback is you can't avoid double validation if you check if the data is valid outside the class (In your Button for eg.)
.
Time matters, but requirements is efficient inputs, repetitive task of great importance, class largely used - you can't be lazy :
=> Handle both UI Validation and Class Validation. Why ? The UI Part addresses the "efficient inputs" part, and the Class Part addresses the "role of the Class". You can use the Validator Function above, or implement much more Exceptions upon Setter like in the other cases above. You're increasing the number of handled Exceptions/Invalid inputs by providing much more information to the user upon Button Click.
Remember : Class largely used. The move here is to implement the maximum coding to handle different cases of invalid inputs, to reduce the amount of code to write elsewhere in your project while still be able to handle all those cases.
.
Time matters, User Friendly Application, repetitive task, important Class :
=> Reconsider the UI Layout and behaviour, validation is mainly UI, but Class is still doing it by itself :
a) User hates Dialog Boxes (whatever DialogBox, message, openfile, etc.. avoid them whenever possible)
b) User hates aggressive colors
c) User hates validation
d) ...... User hates a lot of things..!
The role of the Function Validation above is of importance here : Capture the User Input actions. If it's a TextBox for example, capture the TextChanged Event, then call the Class validation Function. Update information in a Label notifying any encountered error, and change the background color of the TextBox to a friendly color, but related to an error standard, like light Pink. Don't use Color.Red, that's too agressive for most users. Seeing Red 200 times a day can lead to unexpected behaviours at the end of the day.
Only enable the Button when ALL Inputs are valid. Don't make a button per input, User hates endless validations.
.
Time doesn't really matter, User Friendly Application, repetitive task, important Class :
=> Along with the previous option, improve UI response.
Add graphic icons in your label, and/or consider the use of an ErrorProvider in your Form. Users like simple icons rather than long similar messages.
Consider the use friendly sounds to notify poping errors (not everyone is "kind of visual receptive")
.
Time doesn't matter at all, User Friendly Application, repetitive task, important Class :
=> Keep capturing user inputs live, but implement suggestive corrections related to. If it's a TextBox, use AutoCompleteCollection with predefined and fixed Inputs suggestions in the collection when user attempts to input invalid Datas (you'll need a Function for that).
Live disable other inputs when they are incompatible with user's choices/actions.
.
Time really matters, User Friendly recommended, repetitive task, important Class :
=> Don't overload your Form with validations routines.
Create a Custom Control for that specific Input. Overload your custom control with the validations. If your class cannot be used outside this UI, don't bother creating validations inside. Move everything in your custom Control and, even forbid invalid chars (if it's a textbox) whenever possible. In this specific case, you're going to use the UserControl as the Validator component of your Datas.
Otherwise, use the Class validating Function scheme upon Input and display the appropriate error in an User Friendly way whenever possible through that user Control (case where your Class may be used without the UserControl, which would generally be the case)
Etc. etc. etc.
I know I'm more considering the user who's going to use the Application than the one who's going to write the code. But have a look at Baltasarq's answer. In fact, best move is to do both. The three first options are there only for a simple Class of no real importance in your whole Project. We've all created that tiny Class to begin with, and we didn't bother to make strong validation controls. I think that most of us still use those kind of classes. However, as times goes by, some of those classes become more and more used.. then we were faced to the need of stronger validations schemes.
That's the cutting corners way. It's unsafe, but it works... until something happens...
=> Try to do both whenever possible. You don't know what may happen, who is going to use your Class, whether your boss will change his mind and ask you to create a specific UI for that Class to be user friendly for everyone...
Since a while, when I have time upon creating a Class, I'm in fact
creating at least two classes :
- MyClass_Class
- MyClass_Form
- (and perhaps MyClass_UserControl)
- (and perhaps MyChildClassWithUnsafeSetters - used to set value that has already been validated for performance needs)
The core class always provide live Validation capabilities...
EDIT :
Property Validator Function sample using enums...
[Flags]
public enum registrationValidation_Enum
{
Valid = 0x01,
TooLong = 0x02,
InvalidChars = 0x04,
NullEntry = 0x08
// ...
}
This enum can be encapsulated within the class. Enums are easier to handle/memorize/retrieve than Exceptions Classes.
This is the Property Getter/Setter.
class Car
{
private string registration = "Unknown";
public string Registration
{
get
{
return registration;
}
set
{
validate_registration(value, True);
// Setter for the Property.
// Throws an Exception upon invalid value.
}
}
}
This is a Validator Function which is Public :
public registrationValidation_Enum test_registration(
string newRegistration)
{
registrationValidation_Enum checkResult =
registrationValidation_Enum.Valid;
// Do the checks here
if (newRegistration.Length > 10)
{
checkResult = checkResult | registrationValidation_Enum.TooLong;
}
if (containsNonAlphNumericChars(newRegistration))
{
checkResult = checkResult | registrationValidation_Enum.InvalidChars;
}
// ...
return checkResult;
}
And here is the Public version of the Setter :
// this bypass the double check : attempts to set the value if Valid.
// otherwise, either returns a validation result,
// either throws an exception.
public registrationValidation_Enum validate_registration(
string newRegistration,
bool canThrowException)
{
bool isValid = test_registration(newRegistration);
if (isValid == registrationValidation_Enum.Valid)
{
registration = newRegistration;
return registrationValidation_Enum.Valid;
}
else
{
if (canThrowException)
{
string exceptionMessage = "";
if (isValid | registrationValidation_Enum.TooLong)
{
exceptionMessage += "Registration too long"
+ Environment.NewLine;
}
if (isValid | registrationValidation_Enum.InvalidChars)
{
exceptionMessage +=
"Registration contains invalid characters"
+ Environment.NewLine;
}
// ....
Throw New Exception(exceptionMessage);
}
else
{
return isValid;
}
}
}
The public validate_registration(string, false) is there in case :
you don't want to double the validation upon Button Click
you don't live monitor the user Inputs
you don't want to handle cascading exceptions everywhere
you want have control over custom error messages per UI context (you can't always have a label to write errors in)
while attempting to set registration value, all in a row with a button click.
Put the validation result in a variable in any UI-side and display the appropriate notifications/users choices depending on the UI components you can display... This wouldn't have been that simple with Exceptions : Imagine you have both TooLong and InvalidChars. Are you going to show a dialogbox "Too Long" then click button then show another "Invalid Chars" dialog ?
Note : To make the class Localizable, with custom Exception messages using Culture, I would define Class Level Messages (string) variables which values depend on the loaded Culture.
You should have a Core of classes and also those classes related to the user interface. First, create the Core classes (the bussiness logic) of your application. Of course, you should do validation here. Actually, code as if you had no knowledge about who is going to implement the user interface. Also, take into account that users interfaces can change, while the core classes should remain untouched.
When coding the user interface, you wil realise that if you don't do any validation, exceptions will be raised when the user inputs some data cases. This will make you create validation also in the user interface classes.
So, the answer is, you will finally have validation on both parts of the application.
You would use public properties with private members, where you do the checking inside the properties and then assign it to class members.
class Car
{
private string registration;
public string Registration
{
get { return registration;}
set {
if(Validate.registration(value))
registration = value;
else
throw new Exception("Your exception message here");
}
}
}
private void add_Click(object sender, EventArgs e)
{
Car.Registration = txtReg.Text;
}
There are 2 validations:
data type/property limits/parsing;
logical (values between properties);
Have a look at PropertyGrid. It's basic (and pretty sufficient) validation is if your property accept value or throw:
class Car
{
private int _someValue;
public int SomeValue
{
get { return _someValue; }
set
{
if(value > 100)
throw new OutOfRangeException(...);
_someValue = value;
}
}
}
This ensures what Car can validate own properties no matter how they are set (deserialization, PropertyGrid, direct property value, reflection, etc).
Another thing is some logical validation, which can't be performed at instance level, or you simply don't care about it (let instance to be created without exceptions). This one has to be put into editor code (form what is used to create instance).
As for myself, talking about TextBox, I prefer to make custom MyTextBox control which has all parsing related validation (methods GetDouble(), GetInt(), GetIntTime(), etc) and possibility to setup/query it (properties IsDouble, IsInt, etc.).
What's the right way to get my viewmodel to trigger a custom lookup control to throw up a modal dialog that essentially represents that lookup viewmodel? The custom lookup control's data context is that of the parent record view model. The lookup control also has another DependencyProperty that has it bound to a lookupviewmodel property on the parent record view model and this represents a sub lookupviewmodel.
METHOD 1) I currrently use an event on the lookupviewmodel that the custom control knows to listen for.
METHOD 2) I tried throwing a validation exception within the setter of the property on the lookupviewmodel that the lookup control's text propery is bound too. Then I hooked the ErrorEvent in the custom lookup control. But it seems that if the user "corrects" the value from within the dialog while in this event, the original value sticks. And worse, even after I call Validation.ClearInvalid, another ErrorEvent still fires that somehow adds the error back. So everything works here in the sense that all the viewmodels have the correct data, it's just that it seems like the textbox is ignoring that the bound text property has changed on the underlying data source when inside an ErrorEvent. So it seems like I can't correct an error while inside the processing of that error?
Another sub issue within method 2 is that Validation.ClearInvalid doesn't remove the red error border. I had to manually clear the ErrorTemplate too. Is that right?
I'd like to find a way to use natural error handling within the control to get it to throw up the modal dialog.
This isn't what you use events for. Events exist to facilitate decoupling: the object raising the event shouldn't know or care what the object(s) listening to it are doing. You're expecting an event to be able to change the value of a property from inside the property's setter - or worse, your event handler is calling the very property setter that's raising the event that it's handling, which means that you have to do something pretty hackish to avoid a stack overflow.
Your description isn't very clear (you're describing both the problem you're having and the non-working solutions you're trying at the same time, which is confusing), but it sounds like what you're trying to do is something more like:
if (IsValid(value))
{
_Property = value;
}
else
{
_Property = GetValueFromDialog();
}
The problem is that you don't want to have code in your view model that throws up a dialog, since that creates a view model that can't be tested outside of your WPF application.
The answer in this case is to use dependency injection. Create an interface called IDialogService:
interface IDialogService
{
object GetValueFromDialog();
}
Now add this property to your view model:
public IDialogService DialogService { get; set; }
The above code becomes:
if (IsValid(value))
{
_Property = value;
}
else
{
_Property = DialogService.GetValueFromDialog();
}
Create a dialog service for use in your WPF application that actually throws up the dialog and gets the result. When you instantiate your view model in your application, do this:
MyViewModel vm = new MyViewModel { DialogService = new WpfDialogService(); }
Thus, in your application, the property setter will put up the dialog and get the result exactly as you expect it to.
For your unit tests, create a mock dialog that looks like this:
public class MockDialogService : IDialogService
{
private object Result;
public MockDialogService(object result)
{
Result = result;
}
public object GetValueFromDialog() { return Result; }
}
You can then write a test like:
MyViewModel vm = new MyViewModel { DialogService = MockDialogService(ExpectedResult) };
vm.Property = InvalidValue;
Assert.AreEqual(ExpectedResult, vm.Property);
The above is really more a sketch of a solution than a solution - depending on how your application uses dialogs, you may need a lot more features than what are sketched out here. If you take a look at MVVM frameworks you'll find that a lot of them implement dialog services of one kind or another.
You can use a framework like MVVMLight or Prism which allow you to pass payloads between different entities in totally decoupled ways. MVVMLight is very lightweight compared to Prism. It has a concept of Messanger which acts as a system wide event bus. Similarly you have EventAggregator in Prism.
I am building a view (web form) that will display various messages based on the state of a persons License. There are approximately 10 messages that the user will see. I don't really want to create multiple panels and show/hide and populate form fields based on the state...I would rather set a single property on the page...lets just call it:
public String Message
{
get;
set;
}
The message will include html formatting and some of the messages are much longer than other messages...I guess I am looking for a decent pattern to follow so this will be easily manageable...so my presenter will just return the formatted message based on the state of the license.
I am thinking I will create a abstract MessageTemplateBaseClass and classes for each message that build the message...The presenter will return the correct instance of the template based on the license state...
Does this sound like a decent approach?
Yes that would work, or potentially define an IKeyMessage interface that has this definition, and each presenter checks if its view defines this interface, casts it, and sets it appropriately.
HTH.
I have a control in which we show some links to different sites based on some business rules. Currently all business logic to build link list is in control.
I plan to move out the busincess logic from the control.
what will be a good design for this?
can I use any design pattern?
You shouldn't get too caught up in thinking about patterns. Most of the time they are overkill and add too much complexity. Particularly with a trivial scenario like this.
Just utilize good object-oriented practices and you'll be fine. Encapsulate your business logic in another class and provide public properties for your control to access it. Keep it simple!
How about the Model-View-Presenter pattern?
Another good choice might be the Mediator pattern.
Do you really need a custom control for this?
Model-View-Controller suggests that you only have display logic in a control.
Find a solution that allows you to make small changes to a built in control (ListView) and create a custom data set somewhere else to pass to it.
I not sure how you implement your business rules but here is an idea...
I would databind your web forms list control.
public class YourLinks
{
// You could do it by overloading the constructor...
// Again not sure how you determine what links should be displayed...
// If you had consistent types you could make your constructor internal
// and then create a YourLinkBuilder see below...
public YourLinks(User user, Region region)
{
}
public YourLinks(City city)
{
}
// Databind to this method...
public IEnumerable<string> GetLinks()
{
// return your links...
}
}
public class YourLinkBuilder
{
public static YourLinks BuildPowerUserLinks()
{
return new YourLinks(new PowerUser(), new Region("Washington"));
}
public static YourLinks BuildVisitorLinks()
{
return new YourLinks(new VisitorUser(), new Region("Empty"));
}
}
Given the little information provided, I would suggest you create a model of just the links (and its related data). So that you can pass the LinksModel to your views for rendering. Or pass your LinksModel to your existing model (as a sub-model).
Either way, all this data is encapsulated. So if you want to add data to it later, it will not change your method signatures (or general contract). If you want to remove data from it, same advantage. If you want to remove it entirely, its only one object and simplifies the removal.
You can also build links view renderers so that it and only it knows how to visually display the LinksModel. So within your view, you can delegate the visual aspects of the links info to such renderers instead of having logic within your existing view. If you want to change how links view looks later or want to give the user the power of selecting different renditions, you can simply use different renderers rather than jamming your entire code with 'if' blocks.
Jeach!
You should use Model-View-Presenter for sure. In the view, you should have your control.
The control's responsibility should be merely to take input from the user, validate it, and pass that information to the presenter. The presenter should then interact with the model, where your business rules are stored.
From the model, you may wish to return the links that are then passed to the control for display, or you may wish to return some metadata that is passed to another system to retrieve the links.
What I would do is use the Strategy pattern in the model, so that you can easily swap in and out different versions of your business rules.
To abstract interaction with your backend datasource (if you have one) have a look at Martin Fowler's Gateway pattern.