Using DependencyProperty on ViewModel with Entity Framework - c#

I am writing a desktop application in C# using the MVVM pattern with an Entity Framework model. I tend to use DependencyProperties in my VM's and have come to (generally) prefer this system over implementing INotifyPropertyChanged. I would like to keep things consistent. My VM accesses the Entities in the Model and I have managed to keep things pretty separate - the View has no knowlege of the VM except for binding and command names and the Model has know knowlege of the VM.
Using INotifyPropertyChanged in the VM, it seems pretty easy to update the Entities in the Model:
public string Forename
{
get { return CurrentPerson.Forename; }
set
{
if (Forename != value)
{
CurrentPerson.Forename = value;
NotifyPropertyChanged("Forename");
}
}
}
...where CurrentPerson is a Person object auto-created by the Entity Data Model. There is therefore no private field created specifically to store the Forename.
With DependencyProperties, it appears that I would have to create a DP, add the default Property, using GetValue and Setvalue and then use the PropertyChangedCallback in order to update the CurrentPerson Entity. Calling a callback in this situation appears to be adding overhead for the sake of being consistent with my other VM's.
The question is therefore whether one or other of these methods is the way I should do things? In this instance, should I use a DependencyProperty or INotifyPropertyChanged? One thing that should be pointed out is that this will potentially be a very large scale project (with plugins and a lot of database accesses from different machines) and that everything really should be as reusable, and the modules as "disconnected", as possible.

I would recommend using INotifyPropertyChanged instead of DependencyProperty. The main reason I stay away from DependencyProperty in ViewModels is because the DependencyProperty is located in WindowsBase.dll. This ties you to the Windows UI a bit too much (at least IMHO).
Using the INotifyPropertyChanged is a lot easier to maintain since it allows the various plugins to implement it the way they want. If you force Dependency Properties, all viewmodels need to inherit from DependencyObject.
See this article for more details about the use of INotifyPropertyChanged and DependencyProperty: http://kentb.blogspot.com/2009/03/view-models-pocos-versus.html
Another supporting answer: https://stackoverflow.com/a/783154/27669

Related

What is the best practice to implement methods using values of properties in the View Model?

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.

C# WPF MVVM Window OnLoad Binding

My Code behind looks like this...
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
}
My ViewModel looks like this...
class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
bool flag = Application.Current.MainWindow.IsInitialized;
if (flag)
{
// Do something...
}
}
I guess my question is....Does this conform to the MVVM design pattern? The only other way to do this is How to fire a Command when a window is loaded in wpf
I don't know why, but I don't want to use mvvm-light or any other boilerplate code..
Accessing UI component from ViewModel is violation of MVVM pattern.
Application.Current.MainWindow.IsInitialized is breaking that pattern.
Custom behaviours is more in accordance with MVVM. So, i would suggest to go with the approach you mentioned as link in your question.
Accessing UI component breaks the testability of your ViewModel. How would you write testcase for your ViewModel class? Application.Current will be null when you try to test it via unit test and it will throw null reference exception.
One of the main motive of MVVM was to seperate UI logic from business
logic so that business logic can be tested separately without worrying
about its consumer which is view.
There is no "pure" way to do this in MVVM without boilerplate code. In general, you shouldn't need to do work in response to the VIew within your VM - just the concept is a violation of MVVM, since your ViewModel is trying to do something in response the View, and things should always flow the other way.
The ViewModel shouldn't, in a real scenario, care about the View's state at all - it should be doing nothing but presenting data for data binding by the View.
Most of the time when people are attempting this, it's to try to avoid loading data up front. This is something that's typically handled better by pushing the data to load and starting it directly on a background thread within the ViewModel, then updating the property within the VM when it completes. C# 5's async/await language features can be used to simplify this quite a bit.
While it is generally believed that having some load/unload logic is a pattern violation, there is a set of use cases, where it's necessary. E.g. a view model may need to be subscribe to some events. If it didn't unsubscribe when unloaded, it might not be garbage collected, depending on the nature of the subscription.
What would break the pattern is accessing view state from within the view model, e.g. manipulating controls. The role of the view model is to expose data to the view and managing load/unload behaviour is part of this contract. Knowing when a view model is loaded means knowing when to expose that data.
While it is true the view model should not care about state of the view, it must know how to prepare data for presentation in the view. More importantly the view model is a layer between the model and the view that makes them separate. Yet in other words: since 'model' means logic, then 'view model' means logic of getting data to display. And it is also about knowing when to fetch it/make it available/etc.
You may want to take a look at this blog post, which provides a convenient way of making a view model aware of being loaded. It is not 100% correct in terms of MVVM purity, because it passes FrameworkElement back into the view model, but imagine we ignore this parameter.
The sample code below is based on the above blog post, but with purer signatures. You could implement IViewModel interface on your classes:
public interface IViewModel : INotifyPropertyChanged
{
void Load();
void Unload();
}
Then instruct the view to call adequate methods when loaded or unloaded by using an attached property:
ViewModelBehavior.LoadUnload="True"
Notice the last line has its place in XAML - the view is the one that enforces a certain behaviour, not vice-versa.
What you are currently doing is correct and that is how it is really done with other frameworks behind the scenes.
Since you mentioned MVVM-Light, I suggest you can take a look at caliburn micro. It has very nice framework to conform the MVVM Pattern. Caliburn micro makes it easy to hook up bindings with events on the controls. Just check out its documentation and it is still considered as MVVMy..
in particular because MVVM is mainly used to guarantee easy to maintain and testable code, you should bear in mind that Application.Current will be null if you use the MainViewModel in UnitTests. Therefore this code will end in a NullPointerException in your tests.
You should consider using the Initialized event if you want to ensure that something is initialized already. But you create the ViewModel after you called InitializeComponent - I simply would leave the check out.

Databinding to Classmember of Classmember

I need some help about WPF and Databinding.
Let's say I have a ClassA with a member of ClassB. ClassB has again a member,
maybe an int:
ClassB
{
public int MemberOfB { get; set; }
}
ClassA
{
private ClassB _theB;
public ClassB MemberOfA
{
get {return _theB;}
set
{
_theB = value;
// Need to do something here...
}
}
}
When I have a Databinding in XAML like this:
<TextBox Text="{Binding Path=MemberOfA.MemberOfB}"/>
Where the Datacontext of the Textbox is an object of type ClassA.
As you can see, i need to do some computations in the setter of MemberOfA in ClassA.
But with the databinding above, this setter is of course never called, because it binds
to the member of ClassB.
So, how can i get to be informed if the MemberOfA changes (when I Type something into the Textbox)? Are there any best practices?
(Didn't check the code in Visual Studio, so there may be some syntax errors).
Thanks, Walter
The best way to handle this would probably be to make B implement INotifyPropertyChanged. When A gets a new instance of B, have it hook up to the PropertyChanged event (and unhook from the old B's event if necessary).
public B MemberOfA {
get { return _b; }
set {
if (_b != null) { _b.PropertyChanged -= B_PropertyChanged; }
_b = value;
if (_b != null) { _b.PropertyChanged += B_PropertyChanged; }
DoWhatever(_b);
}
}
private void B_PropertyChanged(object sender, PropertyChangedEventArgs e) {
DoWhatever((B)sender);
}
Fundamental problem
In my opinion, all 3rd party vendors ought to implement at least one of NET Framework's standard notification mechanisms, which are:
The original XyzChanged event pattern
INotifyPropertyChanged
INotifyCollectionChanged
OnDependencyPropertyChanged
All of these are fully supported by WPF, so if your vendor implements any of these you should be able to just drop their objects into your WPF application and go.
Unfortunately you will find many 3rd party libraries that don't implement any of these mechanisms: Instead they implement their own custom change notification, or even none at all!
In the rest of this answer I will explain several possible soutions to this problem.
1. Wrap 3rd party objects in wrapper models
You may create a "wrapper model" object to parallel each 3rd party model object that doesn't implement standard notifications. Expose all the 3rd party's properties and methods as your own (yes, this is a lot of code). Register with the 3rd party object's nonstandard notifications mechanism and send standard notifications using INotifyPropertyChanged. This solution is labor-intensive and can be a maintenance headache, but it works well and is many times a good way to make the best of a bad situation.
Many people call these wrapper models "view models" but this terminology leads to confusion: A "view model" is fundamentally a model that models the current state of the user interface such as what the user has open right now, what objects are selected, the current search filter, etc. WPF data binding typically binds to the view model for these types of properties but directly to the model objects themselves for the actual data.
When model objects don't support standard notification, it is common to overload the use of the view model objects to expose both "real" view model properties and also properties from the underlying models. Thus the view model acts both as a real view model and also a wrapper model: The additional properties have nothing to do with UI state but are merely a convenient way to get proper change notification without using a separate wrapper model around the broken 3rd party object.
There is nothing inherently wrong with merging your wrapper model and your view model up into a single object, but it confuses the terminology. For many people I think "view model" has come to be synonymous with "wrapper model" and I think that's a shame. If the wrapper model is kept separate from the view model you get a cleaner interface in your XAML and can more easily adapt once the vendor fixes their change notification.
You may not have time to generate wrapper models for every 3rd party model object, or you may realize that doing so would be impractical due to maintenance issues, updates, or other considerations. It can be a pain to continually be adding and updating your wrapper model every time the 3rd party object changes. In this case I would consider one of the alternative solutions below.
2. Replace DataContext on notification
You may simply tap into the 3rd party's change notification mechanism, and every time an update is signalled simply clear out the relevant DataContext (set it to null), and set it again. This will cause all WPF data bindings to be re-evaluated.
This solution is a bit like killing a fly with a sledgehammer, but it actually works and gets the job done. If it is only simple objects it works well, but as things get more complex it can be messy. If you have ItemsControls or ContentPresenters that create visual trees for your items, setting DataContext to null and back will cause those visual trees to be regenerated. This means you will lose scroll positions, Expander settings, and other UI-specific state within them. You can solve this by binding those properties to a view model to preserve their state.
This solution may be the only solution if the 3rd party's change notification mechanism is broken or inconsistent. It also tends to be the simplest "quick and dirty" solution if you need to get something usable out the door TODAY.
3. Wrap using TransparentProxy / RealProxy
If your 3rd party library includes a sane and consistent but nonstandard change notification mechanism, you have another alternative: You can implement a generalized mapping between the 3rd party mechanism and the standard INotifyPropertyChanged mechanism using the TransparentProxy / RealProxy mechanism of NET Framework.
To do this:
Expose the INotifyPropertyChanged interface on the TransparentProxy, and on your RealProxy handle add_PropertyChanged and remove_PropertyChanged by registering with the 3rd party's event notification system
When the RealProxy receives a property get on a property, do any 3rd party registration required for change notification on that particular property (if not already done) before returning the property
Automatically convert each object returned by the 3rd party property getters into a TransparentProxy of the same object.
Now you can bind your DataContext to an intially-constructed TransparentProxy and from then on pretend the 3rd party library uses a standard change notification mechanism and is completely compatible with WPF.
The TransparentProxy / RealProxy solution is a lot of work to set up and is specific to the 3rd party library's notification mechanism, but once it is working you don't need to worry about out-of-sync UI or losing UI state during refreshes.
4. Use a timer
If the 3rd party library provides no change notifications at all, you can simply set a timer that periodically checks for changes.
Your timer will probably scan the 3rd party object for relevant changes from the values during the last scan. If any are found, it uses one of the previous techniques to provide a standard notification of the changes. In other words, it will signal the wrapper model or RealProxy of the change or it will clear/set a DataContext.
The simplest possible timer solution just periodically sets DataContext to null and then sets it back again without checking for changes.
5. Encourage your 3rd party to implement one of the standard mechanisms
NET Framework defines four different change notification mechanisms, all of which are fully supported by WPF, so it seems inexcusable for anyone to generate objects that support none of these.
Hopefully the next version of your third party library will properly implement one of these standard change notification mechanisms. Contact your vendor and ask them to do so, or at least to create bridge code.
The sad part is, at the moment Microsoft is the worst culprit of all: Neither LINQ to SQL nor LINQ to Entities implements standard change notification on their objects! I think that's too bad because people tend to follow Microsoft's example.

MVVM and DI - How to handle Model objects?

I'm using Caliburn and C#, but I feel like this is a generic MVVM/DI question.
Let's say I have a view model, NoteViewModel, that is passed a model object called Note.
Here is some code:
class NoteViewModel : PropertyChangedBase
{
private readonly Note _note;
public NoteViewModel(Note note)
{
_note = note;
}
public string Title
{
get { return _note.Title; }
set { _note.Title = value; NotifyOfPropertyChange(() => Title); }
}
}
Right now this object is created by calling new() and passing a model object.
Well, that works great, but now I need to add a method that requires an imported class from my DI container.
So do I merely call ServiceLocator.Current.GetInstance() to get it? Or should I design this view model to be created via the DI container and somehow setup a way to pass a Note object?
What is the proper way to design this view model? Basically a "PerInstance" view model that requires a model object for it's use. Does Caliburn have a built-in way to do this?
Caliburn has an interface (IHaveSubject and its typed version IHaveSubject) addressing this kind of scenario: basically it allows a mean to configure the ViewModel with a "subject" after its instantiation, tipically through the container:
class NoteViewModel : PropertyChangedBase, IHasSubject<Note> {
...
}
myNoteViewModel = ... //obtain an instance
myNoteViewModel.WithSubject(new Note());
This solution also integrates well with ISubjectSpecification / Conductor
infrastructure.
Even though post-construction initialization is a simple and effective solution, you may not want (from a pure design perspective) to renounce to an explicit constructor parameter to enforce the need for a Note to istantiate the ViewModel.
In this case I think you have to leverage peculiar features of your DI container, because you may have some parameters of the constructor representing a "real" input parameter, while other may be service dependencies.
Castle Windsor, for example, has a nice feature allowing you to quickly build an explicit (typed) factory for your ViewModel; the factory method will only allow to set the "real" parameters, while all dependencies are managed by the container (see this post for an extensive description of this Windsor feature: http://kozmic.pl/archive/2009/12/24/castle-typed-factory-facility-reborn.aspx)
Can you solve it using hierarchical view models?
To me it becomes more and more clear that I need one ViewModel per View and one ViewModel per model item or collection when building larger application.
That way we can build up ViewModels hierarchically, matching the XAML hierarchy.
The required objects can be defined or injected at the top level by app's main view model then. The nested view models can then access anything the way you design it to make things reachable by them.
About Caliburn, I don't know any specific things about that framework, sorry.
I'm using the ServiceLocator also. And I also "feel dirty" in doing this. But I have resolved to use the YAGNI principle and keep this pattern until I find a compelling payback to the complexity of adding 5 IServices into my constructors, passing them up via 3-4 layers of inheritance to the base classes in which they are needed, and creating everything via the container. Of course my app is evolving, and YAGNI doesn't always last...

WPF Data Binding to external data model

I've recently started develping an application using WPF and I'cant really wrap my mind around following thing:
I have a Domain Model of my application which is simple POCO objects serialized to/from harddisk. Then I have the WPF application and I'd like to bind it to various parts of the model. I need to be able to notify UI of changes to underlying model (eg. implement INotifyPropertyChanged) BUT I want to do that without interfeering with my model (read without modifying current implementation of the model). How can I implement changes notification other than modifying the model?
Reason why I want to do that is that I share the model among multiple projects, only one being WPF, and I don't want to add unncecessary code to the model.
One thing that came to my mind was to create "copy" of the model (with INotifyPropertyChanges and BindingLists etc.) but that seems to be hard to maintainn...
Thanks in advance.
Ondrej
Check this out MVVM
Download its source code see the hierarchy.
Basically you still keep simple POCO objects as your models. Then you create a ViewModel around the model like this:
public class CustomerViewModel : INotifyPropertyChanged
{
readonly Customer _customer;
public CustomerViewModel(Customer customer)
{
_customer = customer;
}
public string FirstName
{
get { return _customer.FirstName; }
set
{
if (value == _customer.FirstName)
return;
_customer.FirstName = value;
OnPropertyChanged("FirstName");
}
}
...
}
I see two possible solutions here:
Use a separate model for WPF screens only (MVVM pattern). This will require maintaining two different models, also be prepare for lots of mapping code.
Use PostSharp to "enhance" your model with all necessary boilerplate code. Here you can find example of automatic INotifyPropertyChanged implementation. Remember that introducing PostSharp to the project is an important decision, so I suggest getting familiar with it first.

Categories

Resources