Data annotation and wpf validation - wpf

Is there any way that I use data annotation as the source of validation in WPF? I want to be able to define a class such as:
class myData
{
[Required]
[MaxLength(50)]
public string Name{get;set;}
}
And then bind it to a field in a view and the wpf validate that user enter some value for this field and also make sure that its length is not greater than 50. I know that I can write a validator for this, but then if I change the maxLength to say 60, then I need to change it in validator and I don't want to have changes in different places.

You need to create a "metadata" definition of the class. You'll need something like this:
[MetadataTypeAttribute(typeof(MyClass.MyClassMetadata))]
public partial class MyClass
{
internal sealed class MyClassMetadata
{
// Metadata classes are not meant to be instantiated.
private MyClassMetadata()
{
}
[Required]
[MaxLength(50)]
public string Name{ get; set; }
}
}
This extends the class with the necessary meta data to support the validation.

Since this question is still left unanswered and I came across it while answering another question that was looking for the same thing, I would share the solution of that question over here too.
The Microsoft TechNet article "Data Validation in MVVM" is a very clean and thorough implementation of using Data Annotations for validation in WPF. I read through the solution myself and would recommend it to others.

Related

Use of Wrapper class for deserialization in callout?

I found the following use of a wrapper class, and was wondering if it is a good practice or whether its just duplication of code for no reason.
//Class:
public class SomeClass{
public Integer someInt;
public String someString;
}
//Callout Class:
public class CalloutClass{
public SomeClass someMethod(){
//...code to do a callout to an api
SomeClass someClassObj = (SomeClass)JSON.Deserialize(APIResponse.getBody(), SomeClass.class);
return someClassObj;
}
}
//Controller:
public class SomeController {
public SomeController(){
someClassObj = calloutClassObj.someMethod();
SomeWrapper wrapperObj = new SomeWrapper();
for(SomeClass iterObj : someClassObj){
wrapperObj.someWrapperInt = iterObj.someInt;
wrapperObj.someWrapperString = iterObj.someString;
}
}
public class someWrapper{
public Integer someWrapperInt{get;set;}
public String someWrapperString{get;set;}
}
}
The wrapper class "someWrapper" could be eliminated if we just use getters and setters ({get;set;}) in "SomeClass."
Could anyone explain if there could be a reason for following this procedure?
Thanks,
James
My assumption (because, code in controller is extra pseudo) is
SomeClass is a business entity, purpose of which is to store/work with business data. By work I mean using it's values to display it (using wrapper in controller), to calculate smth in other entities or build reports... Such kind of object should be as lightweight as possible. You usually iterate through them. You don't need any methods in such kind of objects. Exception is constructor with parameter(s). You might want to have SomeObject__c as parameter or someWrapper.
someWrapper is a entity to display business entity. As for wrapper classes in controllers. Imagine, that when you display entity on edit page and enter a value for someWrapperInt property, you want to update someWrapperString property (or you can just put validation there, for example, checking if it is really Integer). Usually, as for business entity, you don't want such kind of functionality. But when user create or edit it, you may want smth like this.

How to write a commom class for two ViewModel classes?

I have two viewmodel classes called ChangePwdViewModel.cs and ExpiringPwdViewModel.cs.
ChangPwd.xaml binds to ChangePwdViewModel and ExpiringPwd.xaml binds to ExpiringPwdViewModel.
Both have the property as below.
private string _message;
public string Message
{
get { return _message; }
set { _message = value; OnPropertyChanged("Message"); }
}
In each class, there's a function called ValidatePwd() to validate the new password.
In this function, Message property is updated.
Eg.
if (IsAlphaNumeric(this.NewPassword) == false || IsAlphaNumeric(this.CfmPassword) == false)
{
this.Message = "Invalid new password, only characters and numbers are accepted, password must contain at least one character and one number";
this.ResetPasswordFields();
return false;
}
I want to create a common class to write this function and used by two viewmodel. But, How can I update the Message Property of the viewmodels from this class?
How about putting it in a base class:
class ViewModelBase
{
private string _message;
public string Message
{
get { return _message; }
set { _message = value; OnPropertyChanged("Message"); }
}
public bool VerifyPassword(string newPassword)
{
....
}
}
class ChangePwdViewModel : ViewModelBase
{
}
class ExpiringPwdViewModel : ViewModelBase
{
}
Update:
If you can't use a base class because your view models already have a base class then you could use an interface as suggested by others. However this means that you will still have to implement the interface in all your view model classes so you don't gain that much in terms of avoiding multiple implementations (except that you have a contract for your view models then which is usually a good thing to have).
You can achieve some kind of "multiple inheritance" in C# by using a tool like Dynamic Proxy which allows you to create mixins. So you could implement the Message property and password verification in one class and then create a mixin proxy which merges the view model with that implementation. It's not as nice as you will have to create all your view model instances via the proxy generator but it can be made to work. Have a look at this tutorial if it sounds like an option for you.
You could have the two ViewModel classes implement a common interface, say IMessage that implemented a single property - Message.
Then your common class or a function would take a parameter of type IMessage that it could use to update the message.
I would suggest to avoid base classes (could cause potential design issues in future) in such cases, I would rather suggest to pass through constructor an algorithm of validation, smth like this:
public class MyViewModel
{
public MyViewModel(Func<bool> validationAlgorithm)
{
// ... save function to use later for a validation
}
}

Requirements for design-time data source in Report Viewer 2010

What are the requirements for a custom data source to be listed in the 'Data Source' drop-down list when adding a Dataset to a .rdlc report in Report Viewer 2010?
As can been seen from the screen grab, for some reason it is listing potential sources from a variety of referenced assemblies, but I can't see an obvious pattern as to why it is selecting these.
The 'GeneralDataSet' makes sense as that is a strongly-typed Dataset class, but I'm pretty sure most of the others are not, yet the design dialog still lists them.
I'm looking to roll my own custom data source and would prefer it to be selectable from this list.
I think it scans your project file looking for methods that return Lists<> and so on.
So something like:
public class Person
{
public string name { get; set; }
public int age { get; set; }
}
public class GetPeople
{
public List<Person> GetPeopleList()
{
return null;
}
public IEnumerable<Person> GetPeopleIEnumerable()
{
return null;
}
public IQueryable<Person> GetPeopleIQueryable()
{
return null;
}
}
All three show up, so take your pick. (Code is just thrashed out, ignore bad names/practices :))
But when you use a ReportViewer, you will need to manually set the datasets. Selecting it inside the report from what I have found just basically tells it what data to expect. So add an ObjectDataSource or just set it in the code behind.
I noticed the dataset does not appear if the source is exposed as a Property and not a method.
ie this fails to be a selectable data source.
public class FooData
{
public List<string> Data {get;set;}
}
but this will show up as a data source
public class FooData
{
public List<string> GetData();
}
I just had a problem with this also,
my class was returning Lists but would not show up in the datasources list.
I then added a parameterless constructor and it started to show up ( there was not one before ) I assmume this is so the reportviewer can create and instance of it.
eg:
public MyObject()
{
}
I've had a similar problem with custom lists which inherit from List.
You can work around it if your system will allow you to inherit without using interfaces. Ours doesn't.
The project containing this class WILL appear in the DataSource dropdown, and the class itself appears in the DataSet dropdown:
public class AccountList : List<AccountData>
{}
This class will NOT appear as a Dataset, which prevents its project from appearing as a DataSource (notice the "I" in front of AccountData):
public class AccountList : List<IAccountData>
{}
This is a pain because other aspects of our system require the lists to inherit from an interface not a concrete class. I don't know why it doesn't work.

MVVM - RaisePropertyChanged turning code into a mess

New to MVVM so please excuse my ignorance.
I THINK i'm using it right but I find my ViewModel has too many of these:
RaisePropertyChanged("SomeProperty")
Every time I set a property I have to raise that damned property changed.
I miss the days where I could just go:
public int SomeInteger { get; private set;}
These days I have to stick the "RaisePropertyChanged" in everywhere or my UI does not reflect the changes :(
Am I doing it wrong or are other people getting annoyed with the excessive number of magic strings and old school property setters?
Should I be using dependency properties instead? (I doubt that would help the code bloat anyway)
Despite these problems I still think MVVM is the way to go so I guess that's something.
Take a look at this What is the best or most interesting use of Extension Methods you've seen?.
It describes an extension method and a helper method that my Model and ViewModel classes use to enable the following strongly typed (no magic string) properties.
private string _name;
public string Name
{
get { return _name; }
set { this.NotifySetProperty(ref _name, value, () => this.Name); }
}
This is about as simple as I think it can get. Hope it helps.
You could use PostSharp's NotifyPropertyChanged attribute. Then all you have to do is to put an attribute on the class and that's it. E.g.:
[NotifyPropertyChanged]
public class MyClass
{
public string MyProperty { get; set; }
}
It helps to look at things from a different perspective: those are not complicated .NET properties, but simplified dependency properties.
Bindable properties of a view model in WPF are not identical to .NET properties, instead it is a kind of key-value store. If you want light-weight alternative to DependencyObject, you have an ability to implement this key-value store just buy calling certain function in setters - not bad, actually. Far from ideal too, of course, but your point of view is certainly unfair.
It does not get you back to the clean code, but I use a simple extension method to get the property name to avoid problems with magic strings. It also maintains the readability of the code, i.e. it is explicit what is happening.
The extension method is simply as follows:
public static string GetPropertyName(this MethodBase methodBase)
{
return methodBase.Name.Substring(4);
}
With this it means that you property sets are resilient against name changes and look like the following:
private string _name;
public string Name
{
get { return _name; }
set
{
name = value;
RaisePropertyChanged(MethodBase.GetCurrentMethod().GetPropertyName());
}
}
I've written more about this extension method here and I've published a matching code snippet here.
This will help:
"Kind Of Magic"
Effortless INotifyPropertyChanged
[http://visualstudiogallery.msdn.microsoft.com/d5cd6aa1-57a5-4aaa-a2be-969c6db7f88a][1]
as an example for adding it to one property:
[Magic]
public string Name { get { return _name; } set { _name = value; } }
string _name;
Another example for adding it to all the class properties:
[Magic]
public class MyViewModel: INotifyPropertyChanged
{
public string Name { get; set; }
public string LastName { get; set; }
.....
}

Winforms: access class properties throughout application

I know this must be an age-old, tired question, but I cant seem to find anything thru my trusty friend (aka Google).
I have a .net 3.5 c# winforms app, that presents a user with a login form on application startup. After a successful login, I want to run off to the DB, pull in some user-specific data and hold them (in properties) in a class called AppCurrentUser.cs, that can thereafer be accessed across all classes in the assembly - the purpose here being that I can fill some properties with a once-off data read, instead of making a call to the DB everytime I need to. In a web app, I would usually use Session variables, and I know that the concept of that does not exist in WinForms.
The class structure resembles the following:
public class AppCurrentUser {
public AppCurrentUser() { }
public Guid UserName { get; set; }
public List<string> Roles { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
}
Now, I have some options that I need some expert advice on:
Being a "dumb" class, I should make the properties non-static, instantiate the class and then set the properties...but then I will only be able to access that instance from within the class that it was created in, right?
Logically, I believe that these properties should be static as I will only be using the class once throughout the application (and not creating new instances of it), and it's property values will be "reset" on application close. (If I create an instance of it, I can dispose of it on application close)
How should I structure my class and how do I access its properties across all classes in my assembly? I really would appreciate your honest and valued advice on this!!
Thanks!
Use the singleton pattern here:
public class AppUser
{
private static _current = null;
public static AppUser Current
{
get { return = _current; }
}
public static void Init()
{
if (_current == null)
{
_current = new AppUser();
// Load everything from the DB.
// Name = Dd.GetName();
}
}
public string Name { get; private set; }
}
// App startup.
AppUser.Init();
// Now any form / class / whatever can simply do:
var name = AppUser.Current.Name;
Now the "static" things are thread-unsafe. I'll leave it as an exercise of the reader to figure out how to properly use the lock() syntax to make it thread-safe. You should also handle the case if the Current property is accessed before the call to Init.
It depends on how you setup your architecture. If you're doing all your business logic code inside the actual form (e.g. coupling it to the UI), then you probably want to pass user information in as a parameter when you make a form, then keep a reference to it from within that form. In other words, you'd be implementing a Singleton pattern.
You could also use Dependency Injection, so that every time you request the user object, the dependency injection framework (like StructureMap) will provide you with the right object. -- you could probably use it like a session variable since you'll be working in a stateful environment.
The correct place to store this type of information is in a custom implementation of IIdentity. Any information that you need to identify a user or his access rights can be stored in that object, which is then associated with the current thread and can be queried from the current thread whenever needed.
This principal is illustrated in Rocky Lhotka's CLSA books, or google winforms custom identity.
I'm not convinced this is the right way but you could do something like this (seems to be what you're asking for anyway):
public class Sessions
{
// Variables
private static string _Username;
// properties
public static string Username
{
get
{
return _Username;
}
set
{
_Username = value;
}
}
}
in case the c# is wrong...i'm a vb.net developer...
then you'd just use Sessions.USername etc etc

Resources