I am starting with MVVM.
My application uses this "pattern (PM pattern - let's not debate this here :) )"and works fine; The project is very simple and supposedly easy for beginners to get to grips with!! If only it was... :)
There is one thing which is puzzling me, which may have nothing to do with MVVM per se; the PropertyChangedEventHandler.
I am stepping through my code, line by line and can see the call (code below) but I'm not sure why I am calling this handler or what it is doing!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Input;
namespace drMVVM.Model
{
public class TextContent : INotifyPropertyChanged
{
private string text;
public string Text
{
get { return text; }
set
{
if (text != value)
{
text = value;
OnPropertyChanged("Text");
}
}
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
}
I also have a similar layout of code for my viewmodel, but instead of setting the properties, I'm just creating an instance of the object and applying any additional logic.
Is the PropertyChangedEventArgs used to update just the properties of the model that something has changed? If so, why is it implemented in the model class and not just the ModelView? Is it because it can instinctively know whether to just listen for a change or to provide details a notification that a change occurs? If it's a notification (I assume so hence the name of the interface) then what am I notifying in my Model class?
INotifyPropertyChanged is required whenever you want to notify someone about changes of your properties. So if your ViewModel needs to notify the view about changes so the view updates its data binding, then you ViewModel needs to implement it and raise the event with every change of the properties.
Similar, if your model has properties that can change and you want to be notified about, then implement it in your model as well.
It’s not really necessary for something, unless there are automated implications for it; one being the data binding in WPF which needs a hint so it knows that it has to update.
Related
I've been trying to find the correct approach for this problem I got, using Prism with Xamarin Forms:
I've a model class, Customer, that contains another class, Address as a property. In my view, I show fields from both objects. I would like to have a "save" button, that only gets enabled after you've made some changes to those models.
Now, the button is bound to a Command, with the corresponding CanSave() function, as is normal with DelegateCommands. I'm trying to find an approach where I can end up with a single IsDirty property on my view model, that gets to "true" after any changed to the underlying models.
The MVVM approach
First thing I thought was the "purist" mvvm approach. A "flat" view model, with properties for each visual element, implemented as a Prism BindableObject, where each getter/setter gets/sets values from/to the underlying model classes.
That failed though, since SetProperty<> has a ref parameter, where I can't use properties from my models.
The over-engineered approach [?]
Second thing I thought was that, if my inner models were observables themselves, I could listen for changes from all of them, throughout the tree. Which opens up a whole new world of issues. Do I register property change listeners in my View model ? Do I make inner models observables, and have the parents listen for change events on their children and propagate that ?
Won't that observable models approach quickly become event handler hell ?
The simplest thing
And last, the simplest thing possible. I have a flat observable ViewModel, that only reads/writes values to/from the actual inner hierarchical model upon read & save
What do you guys think ?
Maybe I didn't understand your question right, but I'm wondering why you limit yourself to such a small helper function like SetProperty. It has 4 Lines of code. All it does is checking for equality, setting a value and raising an event.
You could easily create another helper function like this.
MyBindableBase
protected virtual bool SetProperty<T>(Func<T> get, Action<T> set, T value, [CallerMemberName] string propertyName = null)
{
if (object.Equals(get(), value)) return false;
set(value);
OnPropertyChanged(propertyName);
return true;
}
Model
class Model
{
public string Property { get; set; }
}
ViewModel
class ViewModel : BindableBase
{
private Model Model { get; set; }
public string Property
{
get { return Model.Property; }
set { SetProperty(() => Model.Property, x => Model.Property = x, value); }
}
}
I think you can shorten the usage, if you introduce some naming rules for the mapping and/or use reflections.
Well, in the end I went for option 3, the simplest thing I could do.
I was leaning towards returning properties from my model, which would be easy, and using the nullable [?.] syntax it would be null-safe too, but I found that at times I'll have to wrap the actual model properties with something that is more UI-friendly, exposing more/different properties than my actual DB model classes.
So, I went for that, until some other complexity forces me to change my mind again :)
Thanks a lot #Sven-Michael Stübe and #adminSoftDK for the help
I am using MEF in a WPF application. I use MEF to create view model objects for my views, and am interested in avoiding memory leaks by ensuring that the MEF CompositionContainer does not keep references to my view model objects.
I am aware of this question and its answers. I carefully avoid using IDisposable, since it doesn't "play nicely" with WPF.
For debug purposes, I would like to write some code that asserts that an object has not been added to the CompositionContainer. This would ensure that I haven't made a subtle change to a view model class that means that it is now not properly being released.
Here is some sample code. How can I implement AssertNotInContainer? Note that in this example it would be trivial to dispose of exportLifetimeContext properly. However, in my more complex scenario I want to be able to rely on the garbage collector rather than IDisposable, since it is hard to determine the lifetime of WPF objects and their associated view models (attached by the DataContext).
namespace Demo
{
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Diagnostics;
class Program
{
static void Main(string[] args)
{
CompositionContainer container = new CompositionContainer(new ApplicationCatalog());
MyOwnerClass demo = container.GetExport<MyOwnerClass>().Value;
// Not going to dispose this...
ExportLifetimeContext<MyLittleClass> exportLifetimeContext = demo.Factory.CreateExport();
// Note that I don't dispose of exportLifetimeContext, since I know that if MyLittleClass obeys
// the proper rules, it won't be added to the container anyway, and exportLifetimeContext.Dispose()
// will do nothing anyway.
MyLittleClass part = exportLifetimeContext.Value;
// I wan't this to assert that part is not referenced in container.
container.AssertNotInContainer(part);
// This is a hacky way that I can confirm that MyLittleClass isn't referenced by the container.
// This causes "Finalized." to be sent to the console.
GC.Collect();
Console.ReadLine();
}
}
[Export]
public class MyOwnerClass
{
[Import]
public ExportFactory<MyLittleClass> Factory { get; set; }
}
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class MyLittleClass
{
~MyLittleClass()
{
Console.WriteLine("Finalized.");
}
}
public static class MefHelper
{
[Conditional("DEBUG")]
public static void AssertNotInContainer(this CompositionContainer container, object part)
{
// What code should I write here?
bool isInContainer = false /* ??? */;
if (isInContainer)
{
throw new InvalidOperationException(
"Part does not meet rules for not being added to CompositionContainer. You have a leak!");
}
}
}
}
MEF Part Lifetime
The MEF documentation includes a useful, though out-of-date, page explaining the lifetime of objects created by MEF. It says the following:
We believe that .Net Garbage Collector is the best thing to rely on for proper clean up. However, we also need to provider a container that has a deterministic behavior. Thus, the container will not hold references to parts it creates unless one of the following is true:
The part is marked as Shared
The part implements IDisposable
One or more imports is configured to allow recomposition
I have an EF 5 entity called Account generated with the standard template.
It has a property AccountTypeId.
When it changes, I need a notification so another field can be updated.
How is this typically done? This is needed for only one property, so I don't want to use a modified template.
AccountTypeId is bound to a ComboBox in the UI in WinForms, so it's not really an MVVM app as I would normally do in WPF.
One way is to go to the EDMX and rename the field to AccountTypeID_Internal (for example), and in the EDMX set the property to Private. Then create a Partial Class.
Generated Account.cs should look like:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace <yournamespace>
{
using System;
using System.Collections.Generic;
public partial class Account
{
private int AccountTypeId_Internal { get; set; }
// other auto generated properties
}
}
Account.Partial.Cs
public partial class Account : INotifyPropertyChanged
{
public Int AccountTypeId
{
get
{
return this.AccountTypeId_Internal;
}
set
{
this.AccountTypeId_Internal = value;
// Do INotifyPropertyChangedLogic
}
}
// Implement INotifyPropertyChanged
}
The advantage of this is that your already written code doesn't have to change at all. The downside is that if you remove the Accout from the edmx and re-add it you will have to go through the edmx steps again.
You can do this with a few lines of code using a NuGet package called PropertyChanged.Fody. The package documentation is on GitHub. See my CodeProject tip "Adding INotifyPropertyChanged to Entity Framework Classes".
I should point out that that technique will implement INPC for every property in the class. If you only want INPC for a single property and you don't want to modify the T4 template or EDMX file then you could leverage the fact that the entity classes are generated with the "partial" keyword, allowing you to add a "wrapper" property in a separate (non-generated) file like Erik Philips described. You would have to modify your existing code to reference the wrapper property but nothing would break when you re-generate the model or entities.
I am currently developping an application which object model and persistence layer is built using the Entity Framework model designer.
One of the requirements I have is to provide a status to my entities that could let me know whenever they are in a "dirty" state (modified), when the status change occurs and, most important, working in a disconnected mode. So I started modifying the T4 template to add a IsDirty boolean property upon generation of those entities, added an event that is fired whenever IsDirty changes and added this.IsDirty = true in the xxxChanged methods of all scalar properties.
Everything works great when the entity is not attached to its context but when attached, whenever a property is changed, thus changing the IsDirty value to false, I receive this exception:
The property 'IsDirty' does not have a valid entity mapping on the
entity object. For more information, see the Entity Framework
documentation.
So what am I doing wrong here? I don't want this property to be mapped in my database as it is just an object status that only matters when the object is "alive". Is there an attribute I should use to decorate the IsDirty property? Or should I derive EntityObject and implement the status mechanism? Or maybe you have any better advice on how to implement this?
Thanks.
Edit: I am using Entity Framework 4.0 with EDM designer.
Here is the piece of code generated into every base entity:
private bool isDirty;
public event EventHandler DirtyStatusChanged;
public bool IsDirty
{
get
{
return this.isDirty;
}
internal set
{
if (this.isDirty != value)
{
ReportPropertyChanging("IsDirty");
this.isDirty = value;
ReportPropertyChanged("IsDirty");
ReportDirtyStatusChanged();
}
}
}
protected void ReportDirtyStatusChanged()
{
var handler = this.DirtyStatusChanged;
if(handler != null)
{
handler(this, EventArgs.Empty);
}
}
I finally found the error myself. The problem lied inside my property setter. Instead of calling ReportPropertyChanged/ing I should have called OnPropertyChanged/ing.
ReportPropertyChanged/ing implies for the context to search for changes between the original and the current entity value but as this property is just a status object that has no mapping to a store, the concept of original value makes no sense, thus making the context failing to find a correct mapping for this property.
Using OnPropertyChanged/ing just fixed it.
I started working with the MVVM pattern in a new project.
Everything is ok, but i came to the following problem.
The implementation looks like this:
I have a MainView, the main app window. In this window i have a telerik RadGroupPanel in wich I host the rest of the app views as tabs.
The rest of the viewModels does not know about this RadGroupPanel which is hosted in MainVIew.
How should i correctly add those views to the RadGroupPanel from the commands in the viewModels?
Thanks.
Have you considered injecting your view into the ViewModel using an interface to maintain separation? I know this breaks MVVM but I've successfully used this on a number of WPF projects. I call it MiVVM or Model Interface-to-View ViewModel.
The pattern is simple. Your Usercontrol should have an interface, call it IView. Then in the ViewModel you have a property with a setter of type IMyView, say
public IMyView InjectedView { set { _injectedView = value; } }
Then in the view you create a dependency property called This
public MyUserControl : IMyView
{
public static readonly DependencyProperty ThisProperty =
DependencyProperty.Register("This", typeof(IMyView), typeof(MyUserControl));
public MyUserControl()
{
SetValue(ThisProperty, this);
}
public IMyView This { get { return GetValue(ThisProperty); } set { /* do nothing */ } }
}
finally in Xaml you can inject the view directly into the ViewModel using binding
<MyUserControl This="{Binding InjectedView, Mode=OneWayToSource}"/>
Try it out! I've used this pattern many times and you get an interface to the view injected once on startup. This means you maintain separation (Viewmodel can be tested as IView can be mocked), yet you get around the lack of binding support in many third party controls. Plus, its fast. Did you know binding uses reflection?
There's a demo project showcasing this pattern on the blog link above. I'd advocate trying out the Attached Property implementation of MiVVM if you are using a third party control.
You can have the list of viewmodels that you need to add controls for in an ObservableCollection in your main window viewmodel. You can then bind the ItemsSource of the RadGroupPanel to that collection and use the ItemTemplateSelector and ContentTemplateSelector of the RadGroupPanel to select the right template to use based on the viewmodel that is bound.