Before .Net 4.5, WPF controls used to leak on custom ICommand implementations that did not use a weak event pattern because they did not unsubscribe from the CanExecuteChanged event of the interface.
We now have the CanExecuteChangedEventManager class and a quick JustDecompile search finds that clases like MenuItem and ButtonBase are using the manager, thus avoiding the leak.
Is there still the need to use a weak event pattern when creating a custom ICommand?
Related
Does the Visual Studio project template known as Template 10 implement INotifyPropertyChanged? Or does it leave that to whatever MVVM toolkit like MVVM Light or PRISM to define that? (Or of course one could roll their own.)
In Template 10, the ViewModelBase implements the BindableBase, and the BindableBase implement the INotifyPropertyChanged.
You can extend the ViewModelBase in your view model, and use the Set(ref _Value, value) method to invoke PropertyChanged event.
Can someone explain What benefits an MVVM framework such as ReactiveUI or MVVM Light provides to Xamarin.Forms application? we can implement INotifyPropertyChanged in our viewmodels without using any of these frameworks.
Am I missing something?
I'm an author of a small MVVM framework for Xamarin.Forms (https://github.com/daniel-luberda/DLToolkit.PageFactory). I'll try to point some advantages of using it as some of features are common for other frameworks too:
Ready to use INotifyPropertyChanged implementation (just inherit from BaseViewModel or BaseModel)
ViewModel oriented Navigation (you can move your navigation logic to view models)
Built-in messaging to easily pass data/arguments between pages or view models
Page caching and reusing (better UI experience as views/pages are reused)
Every page has access to typed ViewModel instance which is automatically instantiated and wired to BindingContext
Those features vary between libraries. Some of more advanced MVVM frameworks offer you a possibility to move your entire project to a different platforms/sdks as they have multi platform support. It may be a nice deal for a larger projects.
Sample code to illustrate some features (the code is called from a ViewModel):
PageFactory.GetPageFromCache<SecondPageModel>()
.ResetPageModel()
.SendActionToPageModel((model) => { model.Message = "Hello World!"; })
.PushPage();
There is more to an MVVM Framework than just INotifyPropertyChanged. To give just a couple of examples there are:
RelayCommand - A class that can provides an implementation of the ICommand interface and allows you to bind a delegate to the view. Useful for buttons
EventToCommand - This allows you to bind an event to a command in your view model. Instead of having to use code behind for UIElement Events
These are just two classes that are provided by an MVVM Framework such as MVVMLight
By using MVVMLight it means that you do not have to implement INotifyPropertyChanged in every project you just make sure your ViewModel inherits from ViewModelBase and you also don't have to write your own implementation in every project for the two classes mentioned above.
The final thing to mention is that you can also install code snippets for MVVMLight. Meaning that writing code is EVEN faster!
For example if you would like a property that raises property changed as well just use the mvvmlight property snippet. And similarly if you would like a RelayCommand property you can just use the mvvmlight RelayCommand snippet
The Model-View-ViewModel (MVVM) architectural pattern was invented with XAML in mind. The pattern enforces a separation of the XAML user interface (the View) from the underlying data (the Model) through a class that serves as an intermediary between the View and the Model (the ViewModel). The View and the ViewModel are often connected through data bindings defined in the XAML file. The BindingContext for the View is usually an instance of the ViewModel. Please click here to see more details and sample code.
You don't need to use ReactiveUI or MVVM Light, you can just use INotifyPropertyChanged interface to notify clients that a property value has changed.Below, you can see my ViewModelBase class code, hope this helps you out;
public class ViewModelBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
In my ViewModel here is how I inherit from ViewModelBase and how I create my property;
public class ImageButtonViewModel : ViewModelBase
{
// ...
private string header;
public string Header
{
get
{
return header;
}
set
{
header = value;
OnPropertyChanged();
}
}
// ...
}
I have been using with great success with Askaiser.Mobile.Pillar, and I do not see anything wrong, I am still investigating, but this has become a great candidate for my projects.
Doc
I hope I have helped.
A greeting
The plain truth is that MVVM Frameworks (and their IOC Containers) are short-cuts to save you time. They come at an extraordinary expense:
They cause a simplistic alignment between views, view models and models. Only one can really belong to another. This is not "IOC" -- it's a hard-coded assignment based on a file naming convention such as this:
MainPage
MainViewModel
MainModel
In a real injection scenario, any number of models could serve any number of view models, provided they implement the proper interface. Also, any number of view models can serve any number of views as long as those view models support the views' interface(s).
MVVM Frameworks create classes through a reflection trick using a string prefix. In the example earlier, the string "Main" allows us to find the page, the view model and the model. But this is not view-model-to-view-model navigation. It is string to view model navigation.
The frameworks create classes using Activator.CreateInstance, which creates havoc on the compile-time linker.
The frameworks instantiate using hyper-simplistic constructor parameter logic. Modern programs use instantiation as a form of control. In these frameworks, there is no real control.
The complete code for these remarks is at https://github.com/marcusts/xamarin-forms-annoyances. See the solution called MvvmAntipattern.sln.
The GitHub site also provides links to a more detailed discussion on this topic.
I've just created my first c# / XAML application using mvvmlight and I've tried to implement the MVVM pattern as best I can (WP8 app). However, I've slowly morphed my code in to a certain style and I don't think its correctly implementing the pattern! Any advice on how things are supposed to be would help enormously.
For example, using mvvmlight I am making heavy use of the ViewModelLocator. Some of my viewmodels get created right away, like the SettingsViewModel (there is a SettingsView).
SimpleIoc.Default.Register<SettingsViewModel>(true);
And then elsewhere in my project, my other viewmodels will directly access this viewmodel for occasional information via a property or a method... like this;
mySetting = ViewModelLocator.SettingsStatic.GetSomeSetting(var);
My concern is that my viewmodels are talking to each other in this way more and more. The issue with this is that they probably can't be tested independently now because they require or assume the existence of other viewmodels.
Any pointers here would be great!
EDIT: Another example is having a PersonView, and the PersonViewModel has some helper methods for UI display. In some cases I have other views that need to display this info.... and I use the viewmodellocator to get to them, rather than writing the helper methods again in the current viewmodel.
You are right in thinking that viewmodels being dependent on viewmodels is going to cause trouble. When I need to have access to "global" settings in my app, I use an interface that can be injected in the constructor of the view model. So, You can create an ISettingsService that contains the properties and methods you need. You also create a design time setting service that mimics or fakes the data/properties of the ISettingsService Interface
then in your view model locator you use this:
if (ViewModelBase.IsInDesignModeStatic) {
SimpleIoc.Default.Register<ISettingsService, DesignSettingService>();
} else {
SimpleIoc.Default.Register<ISettingService, SettingService>();
}
Create the DesignSettingService and SettingService which both implement the ISettingsService.
As for you vewmodels, the SimpleIOC will resolve/inject the required elements passed into the constructor of the class. If you have a class/viewmodel called MyViewModel and it wanted to use the settingsservice then you would define the constructor like this:
private ISettingsService _SettingsAccess;
public New(ISettingsService SettingsService)
{
_SettingsAccess = SettingsService;
SettingProperty= _SettingsAccess.GetProperty;
}
This keeps the viewmodels decoupled as this service is resolved in the constructor, that way you can change the implementation of your ISettingsService without breaking every viewmodel that uses it.
I use a INavigationService to handle all the navigation events in my app, this allows me to cancel navigation based on another viewmodels properties without needing the other viewmodel to be directly called/referenced by the current one.
One view model should never directly call another view model. Using this method you can pass as many "services" as are needed to the viewmodel. Every viewmodel I use gets a dataservice that connects to my model in addition to the navigationservice. Ie. A viewmodel that deals with people gets an IPeopleDataService where this service contains all the CRUD operations that affect the database. That way I can change the people objects in the database and service functions without having to change the people viewmodel as well.
I hope this helps.
I am using MVVM and I would like to communicate between viewmodels. I have a user control that contains another user control inside it, and I would like the parent usercontrol to run some code when a property in the child is changed. I have seen several ways to communicate between viewmodels, such as using MVVM Light Messenger, or PRISM Event Aggregator, but I was hoping there was some way to accomplish this simply by somehow subscribing to the PropertyChanged event raised through the INotifyPropertyChanged implementation.
There is an answer by Matt Hamilton in this post but I have trouble implementing it because it needs a DependencyObject, and my ViewModels are POCOs rather than DOs
Is there some way of using the INotifyPropertyChanged system, as I would prefer to not have to implement a messaging system. If not is a messaging system the best? I also saw an example where some guy just used the code behind of the view to help pass the property, however I don't want to break the MVVM pattern as I wanna do some testing at a later stage.
There definately multiple ways to handle your scenario. One is certainly to use the INotifyPropertyChanged implementation to propogate your event. The issue is that container would need a direct reference to the child ViewModel to subscribe to the PropertyChanged event.
class ParentVM
{
private const string SomePropertyName = "SomeProperty";
public ParentVM()
{
ChildVM child = new ChildVM();
child.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(child_PropertyChanged);
}
void child_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == SomePropertyName)
{
//Do something!!!
}
}
}
You could also explicitly define an event and subscribe to it.
Personally I would pass a reference of the parent viewmodel to each child viewmodel to have direct access.
I tend to avoid the MVVM Light "Messenger" as much as possible. (it's kind of useless when using IoC containers but that's another story)
With the MVVM pattern, how does one go about dynamically binding
an ICommand to the click event of a hyperlink inside of a
RichTextBox?
It's a few steps to get there, but you can do it.
You have to use a bindable rich text box, rather than the one that comes with WPF which is not something you can bind. Details here: http://michaelsync.net/2009/06/09/bindable-wpf-richtext-editor-with-xamlhtml-convertor
Once you have that, you'll have a Rich Text Editor that you can bind to a FlowDocument in your ViewModel.
When your FlowDocument is created, hookup a handler for the Hyperlink.ClickEvent in your ViewModel:
Here's the call that adds the handler to the FlowDoc
TheDocument.AddHandler(Hyperlink.ClickEvent,
new RoutedEventHandler(HandleHyperlinkClick));
//Here's the handler definition
private void HandleHyperlinkClick(object sender, RoutedEventArgs args)
{
Hyperlink link = args.Source as Hyperlink;
//...
}
This is the only thing I've ever seen done. FlowDocuments are a little strange because they are sort of a data type and sort of a visual element so in some sense it feels wrong to have it reside in your ViewModel, but this is the way to go.
You find a lot scenarios where it is not possible to use wpf data binding. In these scenarios you can create a new control (e.g. inherit from RichTextBox) and provide the missing dependency properties so you can use data binding.
However, creating a new control to handle simple scenarios is inefficient. It's not forbidden to implement code in the View's code behind file and this makes often more sense than creating a new control.
A concrete example how this can be done is shown in the ViewModel sample of the project:
WPF Application Framework (WAF)
http://waf.codeplex.com