I have been looking into DataAnnotations and creating my own DataAnnotations for future use - mainly in MVC4 (which is fairly easy it's safe to say). I want to verify how useful, effective and easy to use they will be if I use the same Model classes in a WPF project.
public class Customer
{
public int Id { get; set; }
[Required()]
public string Name { get; set; }
}
public class ViewModelBase : IDataErrorInfo, INotifyPropertyChanged
{
//... (INotifyPropertyChanged)
public string Error
{
get
{
return string.Empty;
}
}
public string this[string columnName]
{
get
{
//According to tutorials, something here
return string.Empty;
}
}
}
So if I were to move on to creating a CustomerViewModel which inherits from the base class, would I have to present a subset view of the model properties like:
public class CustomerViewModel : ViewModelBase
{
[Required]
public string Name { get; set; }
}
Meaning I have to implement the annotations again, or is it possible to just use the model and somehow reflect model validation back to the front end using WPF's MAGICAL binding?
I have been looking at numerous articles, but none of which seem to be neat or very consice - such as:
http://blog.paulbetts.org/index.php/2010/04/27/wpf-data-validation-using-dataannotations/
Why would you put another Name property in your viemodel?
If you have a Customer property in your viewmodel, you can access it in you xaml like:
{Binding Customer.Name}
This will automatically take your dataanotations from your model class.
Edit: For a good example see: http://www.codeproject.com/Articles/98681/Validating-User-Input-WPF-MVVM
Related
I'm writing a small wpf desktop application. My BaseViewModel looks like this:
public abstract class BaseViewModel : INotifyPropertyChanged, IComparable<BaseViewModel>
{
public abstract string GetDisplayText();
public abstract string GetImageName();
// INotifyPropertyChanged
}
I was looking for a best paxis for mvvm. The most say, that there are multiple ViewModels for one Model and I agree to it.
Because I want that all ViewModels of the same type handle the basics in the same way, i thougth they should derived from each other.
public abstract class BaseCustomerVm : BaseViewModel
{
public abstract string Name { get; set; }
public abstract int Number { get; set; }
public abstract bool IsPerson { get; set; }
public override string GetDisplayText()
{
return Name;
}
public override string GetImageName()
{
if (IsPerson)
return "Person";
else
return "Company";
}
}
public class Customer1Vm : BaseCustomerVm
{
public override string Name { get; set; }
public override int Number { get; set; }
public override bool IsPerson { get; set; }
}
To implement this, I have the following options:
Version 1:
public class Customer2Vm : BaseCustomerVm
{
public override string Name { get; set; }
public override int Number { get; set; }
public override bool IsPerson { get; set; }
// Further Properties
}
Version 2:
public class Customer2Vm : Customer1Vm
{
// Further Properties
}
In my search, I read ViewModels shouldn't derive from each other. This was also answerd in this post. My questions are:
Why should I not derive in this way?
What would be the correct way to handle sutch basics with no inheritance?
Inheritance shouldn't be an issue until you reach the point where you need to inherit from more than one (base) view model, i.e. if you have several different base view models that provide their own common base functionality.
Since you can't inherit from more than one class in C#, you then need to break out the common functionality into reusable components that you can inject into your view models.
But the only way you will be able to directly bind to some common properties that are defined in a class is to use inheritance and there is nothing wrong with inheriting from a chain of different base view model classes. In fact, this is a pretty common approach in my experience. Most of the types used in the view (Control, FrameworkElement, etc.) also do this.
As far as if Customer2Vm should derive from Customer1Vm; I think you want the classic inheritance question:
Does Customer2Vm have a "is-a" relationship with Customer1Vm?
Only you know; but based on the names I would doubt it. Sounds to me like they should both be deriving from BaseCustomerVm.
As far as whether or not you should be using inheritance at all; I would say that it largely seems OK here. If you wanted to avoid it (and strictly prefer composition) I would suggest making your VMs implement an ICustomerVm interface to get the properties; and then the consumer would use services to get the display text and image name. I would probably stick with what you have (assuming its more or less exactly what you've shown).
I have a class with some properties with DisplayNameEx attribute, which is derived from DisplayNameAttibute:
public class Settings
{
[DisplayNameEx("User")]
public UserData User { get; set; }
}
public class DisplayNameExAttribute : DisplayNameAttribute
{
public DisplayNameExAttribute(string id)
{
}
}
I pass as string id ALLWAYS name of my property, so it would be easier writing code this way:
public class Settings
{
[DisplayNameEx()]
public UserData User { get; set; }
}
Property name I can get here with CallerMemberName attribute:
public class DisplayNameExAttribute : DisplayNameAttribute
{
public DisplayNameExAttribute([CallerMemberName] string propertyName = null)
{
//propertyName I get, what about class name (Settings in my case)?
}
}
Is it possible to get class name also?
It's impossible. Best way in your case is parameter with class name in the constructor of the attribute:
public class DisplayNameExAttribute : DisplayNameAttribute
{
public DisplayNameExAttribute(string className = null)
{
}
}
and then use it like this:
public class Settings
{
[DisplayNameEx("Settings")]
public UserData User { get; set; }
}
I used a similar technique before .NET 4's localizable DisplayAttribute. From .NET 4 I use the DisplayAttribute because it supports localization and it's much more powerful.
I personally would not recommend your idea because of mainly two reasons.
Potential refactoring issues. If one renames your property, he doesn't have any idea that he should also rename the resource with the same name. Same stands for class names. After a few months even you can forget it time to time.
The code is not straightforward. Other developers could not easily understand what your attributes are doing, and even hard to see at first glance that it's related to localization.
I think the best is just to put there those strings.
I've been getting my head into WPF the last few days, coming from a WinForms background, I just love the flexibility, especially in terms of binding.
However, I had a question after reading the following article on MVVM: http://blog.alner.net/archive/2010/02/09/mvvm-to-wrap-or-not-to-wrap.aspx
How to go about Models I have no control over, I cannot add interfaces to it, etcetera, I can only use them as-is?
Looking at the article, one option for me is to just directly expose the Model in my ViewModel, but would this be a good way to go about it? I could also use the wrapping option, but how do I bubble changes to those bubbles back to the ViewModel if they don't have a INotifyPropertyChanged interface? Are there any other options that allow TwoWay-binding to these Models?
EDIT:
Consider the following classes as models I cannot modify, what are my options:
[DataContract]
public class NPCTypeData
{
[DataMember]
public string Name;
[DataMember]
public List<NameAlias> Emotions;
}
[DataContract]
public class NameAlias
{
[DataMember]
public string Name;
[DataMember]
public string Alias;
}
I don't really care about the code required to turn these into bindable classes, I just want one or more examples on where to start with nested dependencies like this.
Do I copy all data to a Model that does have bindable properties and just leave these for serialization, do I wrap them, or what?
I agree with Henk, and would add that one option can be the "dynamic proxy class creation" which is what entity framework does. Basically: you have your POCO objects, and Entity framework can attach dynamically the necessary functionality to track the changes on model.
There's also an option to inherit from a class, and decorate the class with AOP attribute which generates all the necessary plumbing on the fly.
You can google for:
AOP INotifyPropertyChanged - http://www.postsharp.net/
Automatic INotifyPropertyChanged using Dynamic Proxy - http://jonas.follesoe.no/2009/12/23/automatic-inotifypropertychanged-using-dynamic-proxy/
When I had such problem, I basically used Henk solution, creating new classes and wrapping each property, using AutoMapper. Did it work & was it maintable? Yes, it worked, and it was maintable. Was it painful? Yes.
public class NPCTypeDataViewModel
{
public string Name {
get;
set;
}
public List<NameAliasViewModel> Emotions {
get;
set;
}
public NPCTypeDataViewModel(NPCTypeData data){
Name = data.Name;
Emotions = data.Emotions.Select(x => new NameAliasViewModel(x))
.ToList();
}
public NPCTypeData GetModel(){
var ntd = new NPCTypeData(){
Name = Name,
Emotions = Emotions.Select(emo => emo.GetModel())
.ToList()
};
return ntd;
}
}
public class NameAliasViewModel
{
public string Name {
get;
set;
}
public string Alias {
get;
set;
}
public NameAliasViewModel(NameAlias alias){
Name = alias.Name;
Alias = alias.Alias;
}
public NameAlias GetModel(){
return new NameAlias(){
Name = Name,
Alias = Alias
};
}
}
My goal is to do TwoWay binding off a generated EntityFramework model.
What is the best way to implement NotifyPropertyChanged on properties in a generated entity model?
For example, suppose I have this entity from a database:
public partial class Survey
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool Answer { get; set; }
}
I then create a ViewModel...
public class SurveyViewModel : ViewModelBase
{
private Survey _survey = new Survey();
public Survey
{
get { return _survey; }
set
{
_survey = value;
}
}
}
How could I achieve 2 way binding other than writing dependency properties for every single property in the entity model, like so...
//below the declaration of the Survey entity in the viewmodel
public string FirstName
{
get { return Survey.FirstName; }
set
{
Survey.FirstName = value;
NotifyPropertyChanged("FirstName");
}
}
//This works but is very time consuming for large models
Let me know if I'm attempting this wrong...
PropertyChanged.Fody may be what you are looking for:
// Non-auto generated partial class declaration
[ImplementPropertyChanged]
public partial class Survey
{
}
As commented by TyCobb, this question has been asked repeatedly and the result remains the same... here is a summary.
While there are ways pollute your data models with UI accommodating
features such as INotifyPropertyChanged, the MVVM mantra teaches us
that it is the View-Model's job to interact with the UI and the
Data-Model should remain as pure as possible (POCO).
So what? How do we keep to MVVM but avoid the boiler-plate codes of exposing individual properties on the View-Model?
From experience, calling a RaisePropertyChanged is not reserved only for property setters but could be used to manually raise a property changed for a model that has had its own properties modified, thus, cause the UI to update.
Here is a code example...
public class SurveyViewModel : INotifyPropertyChanged
{
private Survey _survey;
public Survey Survey
{
get { return _survey; }
set
{
_survey = value;
RaisePropertyChanged(() => Survey);
}
}
public void ModifySurvey()
{
// Modify a property of the model.
Survey.FirstName = "Modified";
// Make other modifications here...
// Notify property changed
RaisePropertyChanged(() => Survey);
}
}
I've got 2 classes with many different properties and one similar property:
public class A
{
// Lots of specific properties
[Display(Name="Dun and bradstreet number")]
public string DunAndBradstreetNumber {get;set;}
}
public class B
{
// Lots of specific properties
[Display(Name="Dun and bradstreet number")]
public string DunAndBradstreetNumber {get;set;}
}
I realise I have an abundance of choice and I just want to make sure i'm choosing the most semantically correct and popular choice.
1:-----------
Should I declare another class:
public class DunAndBradstreetNumber
{
[Display(Name="Dun and bradstreet number")]
public string DunAndBradstreetNumber {get;set;}
}
and then make class A and B have pointers inside them eg.?
public class A
{
public DunAndBradstreetNumber DunAndBradstreetNumber { get; set; }
}
or
2:-----------
inherit from the DunAndBradstreetNumber?
public class A : DunAndBradstreetNumber
{
//...
}
3:-----------
declare a global function and put that in the get method of each DunAndBradstreetNumber?
public class A
{
public string DunAndBradstreetNumber {
get
{
// Run some function that I may need help on to apply property validation via attributes to
}
set;
}
}
Any more better choices?
My class A and B are domain models using entityframework if that helps at all.
The problem i'm trying to solve is to not have to declare the validation and display attributes twice in different models.
P.S - your opinion is fine... I just want to know the eventualities of the choice I have to make here (albeit its relative insignificance).