DeutschEnglish

Apr 16

Data binding and image cache

One of the comfortable things in WPF data binding is the fact that a lot of types are converted automatically during binding. One example is the Image control and its Source property: This property is of type ImageSource, but it also accepts string input. To illustrate this, let’s assume that you have some string property in your Viewmodel that points to some local image on your hard drive:

private string _path;
public string Path
{
	get { return _path; }
	set { _path = value; RaisePropertyChanged("Path"); }
}

public MyViewmodel()
{
	Path = @"C:\image.png";
}

The View contains an Image control that binds to this string property:

<Image Source="{Binding Url}" />

The problem with this type of binding is that the image is loaded directly from the file to be rendered on the screen – trying to modify, swap, or even rename the file while the application is running will fail because the file is in use and locked by our WPF application.

The reason for this is that the automatic type conversion from string to ImageSource uses default settings and there is no way to customize it. If we’d manually create a BitmapImage (which inherits from ImageSource and can therefore be used as input to the image’s Source property), we’d set its BitmapCacheOption property to OnLoad, since this loads the image into memory at load time and instantly releases the image file. However, it’s unpleasant to hold an object of type BitmapImage in the Viewmodel (e.g. when targeting multiple platforms and keeping all Viewmodels within a Portable Class Library, the BitmapImage can not even be instantiated within the Viewmodel since it’s WPF specific).

The elegant solution here (as in many other cases) is a binding converter: It converts the Viewmodel’s string property to a platform-specific BitmapImage while resolving the binding expression, and sets the custom cache option during this process:

public class ImageConverter : IValueConverter
{
	public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
	{
		var path = value as string;
		if (path != null)
		{
			var uri = new Uri(path);
			var bitmap = new BitmapImage();
			bitmap.BeginInit();
			bitmap.UriSource = uri;
			bitmap.CacheOption = BitmapCacheOption.OnLoad;
			bitmap.EndInit();
			return bitmap;
		}
		return DependencyProperty.UnsetValue;
	}
}

This solution keeps the Viewmodel clean, while the binding expression in the View’s XAML code needs only be complemented by a short converter reference:

<Image Source="{Binding Url, Converter={StaticResource ImageConverter}}" />

Permanent link to this article: http://www.mobilemotion.eu/?p=1487&lang=en

Mar 31

[MVVMbasics] Passing custom parameters during event-to-command redirection

Notice

All blog posts with a title that starts with [MVVMbasics] are related to the MVVMbasics framework. If you are only interested in my regular blog posts and not in MVVMbasics, ignore these. To list all articles covering MVVMbasics, go to http://mvvmbasics.mobilemotion.eu/documentation!

In version 2.0 of the MVVMbasics framework, a simple way to redirect a UI event directly to a Viewmodel Command has been introduced, via the EventToCommand keyword and the Command attached property:

<ListBox SelectionChanged="EventToCommand" mvvm:Event.Command="{Binding ListSelectionChangedCommand}" ... />

This can be used as a short cut in many situations to avoid including the Interaction framework (which usually results in long XAML code lines) or invoking Viewmodel Commands from within code-behind event handlers.

With the 2.2 release, this feature has become more flexible: An additional attached property CommandParameter has been introduced that allows passing custom parameters to the target Command instead of the generic event arguments! The CommandParameter can be specified either as fixed value, or through Data Binding:

<ListBox x:Name="List"
         SelectionChanged="EventToCommand"
         mvvm:Event.Command="{Binding ListSelectionChangedCommand}"
         mvvm:Event.CommandParameter="{Binding ElementName=List, Path=SelectedItem}" />
<CustomControl DoubleClick="EventToCommand"
               mvvm:Event.Command="{Binding ActivatedCommand}"
               mvvm:Event.Command="123" />

In the Viewmodel, you instantiate the BaseCommand with a target method that accepts one parameter of type object, just as in the previous version. This parameter, however, will contain the passed parameter. Of course, it is still possible to get the raw event arguments forwarded to the Command by simple omitting the CommandParameter property, as in this case the event args will be automatically used as parameter.

Be aware, though, that you still need to declare the mvvm namespace in the View’s XAML header. In addition, please notice that Windows Phone Silverlight projects do not support the EventToCommand keyword due to a bug in the Silverlight platform. Instead you’ll need to attach the EventToCommand handler to the desired event in C# code-behind, as explained in detail in the original article presenting the MVVMbasics event-to-command binding solution!

Permanent link to this article: http://www.mobilemotion.eu/?p=1477&lang=en

Mar 22

[MVVMbasics] Attribute-based bindable property declaration

Notice

All blog posts with a title that starts with [MVVMbasics] are related to the MVVMbasics framework. If you are only interested in my regular blog posts and not in MVVMbasics, ignore these. To list all articles covering MVVMbasics, go to http://mvvmbasics.mobilemotion.eu/documentation!

Previous versions of the MVVMbasics framework provided the Set method to help shorten bindable property declarations in Models and Viewmodels:

private string _someText;
public string SomeText
{
	get { return _someText; }
	set { Set(ref _someText, value); }
}

The Set method sets the property’s value and raises the PropertyChanged event if necessary. This allows the reduction of the setter method’s body to only one line, however the full property declaration still needs several lines of code since it is still necessary to define getter and setter method as well as the backing field manually.

MVVMbasics 2.2 finally supports the use of auto-properties as bindable properties. Properties defined in Models or Viewmodels that are marked with the MVVMbasics.Attributes.MvvmBindable attribute automatically raise the PropertyChanged event when their value is updated:

[MvvmBindable]
public string SomeText { get; set; }

While this significantly reduces code lines for bindable property declaration, it can still be simplified by using the [MvvmBindableProperties] attribute: In Viewmodels that contain many bindable properties, this attribute can be assigned to the Viewmodel class – in this case, all public properties defined within the Viewmodel class are treated as bindable, meaning that they will raise the PropertyChanged event when changed. To exclude single properties from this general rule, they can be marked with the [MvvmBindableIgnore] attribute:

[MvvmBindableProperties]
public class MyViewmodel : BaseViewmodel
{
	public string SomeText { get; set; }  // raises the PropertyChanged event
	
	public int SomeNumber { get; set; }  // raises the PropertyChanged event
	
	[MvvmBindableIgnore]
	public bool SomeInternalProperty { get; set; }  // does not raise the PropertyChanged event!
}

Please note that the [MvvmBindable...] attributes only work on properties that are defined within classes that inherit (directly or not) from the BaseModel or BaseViewmodel class! The reason for this limitation is that the automatic event raising mechanism that is responsible for all this magic relies on the NotifyPropertyChanged method which is defined by the BaseModel and BaseViewmodel classes.

Sometimes, bindable properties need to raise the PropertyChanged event more than once: The most typical case is a property that specifies only a getter method which returns a combination of several other properties:

public string FirstName { get; set; }

public string LastName { get; set; }

public string FullName
{
	get { return String.Format("{0} {1}", FirstName, LastName); }
}

The [MvvmBindable...] attributes even work in this case, since the underlying automatic event raising mechanism work in two iterations: First, all properties that don’t define a setter method are analyzed, and all the properties that are referenced in their getter methods are stored. In the second iteration, all properties that define setter methods are adapted, in order to raise their own PropertyChanged as well as all their dependent properties’ events! Note that for this to work, also the “read-only” properties (that only contain getter methods) need to be marked with the [MvvmBindable] attribute, or the whole class needs to be marked with the [MvvmBindableProperties] attribute.

public class MyViewmodel : BaseViewmodel
{
	[MvvmBindable]
	public string FirstName { get; set; }  // raises the PropertyChanged event for properties FirstName and FullName

	[MvvmBindable]
	public string LastName { get; set; }  // raises the PropertyChanged event for properties LastName and FullName

	[MvvmBindable]
	public string FullName
	{
		get { return String.Format("{0} {1}", FirstName, LastName); }
	}
}

Of course, the conventional way of creating a backing field and calling the Set method inside the property’s setter method is still available. For complex property declarations where the automatic event raising mechanism fails, you can still rely on this approach. Also if you like to automatically call a certain action before or after the property update, the Set method might be the better solution. All of the options it offers is documented in the article New version 2.0 features #2: Simplified Data Binding with more flexibility.

Permanent link to this article: http://www.mobilemotion.eu/?p=1466&lang=en

Mar 18

[MVVMbasics] Targeting the Android and iOS platforms via Xamarin.Forms #2

Notice

All blog posts with a title that starts with [MVVMbasics] are related to the MVVMbasics framework. If you are only interested in my regular blog posts and not in MVVMbasics, ignore these. To list all articles covering MVVMbasics, go to http://mvvmbasics.mobilemotion.eu/documentation!

Project setup in Xamarin Studio:

When using the Xamarin Starter, Indie, or Academic license (or when using Mac OS), it is not possible to use Visual Studio as IDE, instead you might be forced to use Xamarin Studio for development. In this case, you can basically follow the same steps for setting up the project structure as if you were using Visual Studio, however there are a few items that need special attention:

  • Xamarin Studio doesn’t support the creation of Windows Phone applications. Therefore, the solution won’t contain a WinPhone project.

    I’d strongly recommend to add an additional Portable Class Library (PCL) to the automatically created projects that contains all Data Models, Viewmodels, and Service interfaces. In this case, you can create a separate Windows Phone solution in Visual Studio, add a reference to this PCL project, and create a WinPhone application out of the given Models and Viewmodels. In this case, you are not even restricted to using Windows Phone Silverlight (as you would be if using pure Xamarin.Forms), but the Phone project can also be a WinRT App that also runs on Windows 8 devices. (Of course, in this case the effort is a little higher than with Xamarin.Forms-only project, since the Views and Service implementations must be created individually for the Silverlight / WinRT part.)

  • The use of an additional PCL project that contains Models and Viewmodels, as suggested above, also ensures that the App can be ported to other platforms (e.g., WPF) at a later point in time. Alternatively, this PCL can also be created in Visual Studio as part of a WPF solution, and referenced from Xamarin Studio at a later point in time to create a Xamarin.Forms App that provides the same functionality as the WPF application.

  • The MVVMbasics NuGet package contains PowerShell scripts that need to run during package installation in order to add all necessary assembly references. When adding NuGet references through the visual NuGet Package Manager using Xamarin Studio on Mac OS, these PowerShell scripts are not executed. Instead, I recommend to install the NuGet PowerShell Console and use this add-in for adding the MVVMbasics reference.

    To do so, choose the Package Console Extension item from the View -> Pads menu after the NuGet PowerShell Console add-in has been installed, and type Install-Package MvvmBasics to add the MVVMbasics framework to the current project!

Implementing Views:

When creating pages, make sure to add a new item of type Forms Xaml Page as this will allow you to specify the page’s content in XAML code. All pages that shall be automatically assigned their Viewmodel by the MVVMbasics NavigatorService must be derived from the MVVMbasics.Views.BaseView base class. All pages generated by Visual Studio or Xamarin Studio usually are derived from the Xamarin ContentPage class, so you must adapt each page’s base class in both C# and XAML code.When referencing the MVVMbasics.Views namespace in XAML, note that it is defined within the MVVMbasicsXF assembly:

xmlns:views="clr-namespace:MVVMbasics.Views;assembly=MVVMbasicsXF"

The MVVMbasics.Views.BaseView class itself inherits from Xamarin.Forms.ContentPage, so you may design the page’s content as if it was a default ContentPage. The creation of other Xamarin page types (e.g., TabbedPage, CarouselPage, …) is not supported by MVVMbasics at the moment, however the MVVMbasics framework provides an alternative for using NavigationPages as shown in the following section Implementing the global App class.

In addition, the MvvmNavigationTarget attribute should be added to each View class, as this enables the automatic assignment of Viewmodels to View. In summary, a sample MVVMbasics page could be implemented as follows:

<?xml version="1.0" encoding="utf-8" ?>
<views:BaseView xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:views="clr-namespace:MVVMbasics.Views;assembly=MVVMbasicsXF"
             x:Class="MyApp.Views.MyPage">
	<Label Text="{Binding DisplayText}"/>
</views:BaseView>
using Core.Viewmodels;
using MVVMbasics.Attributes;
using MVVMbasics.Views;

namespace MyApp.Views
{
	[MvvmNavigationTarget(typeof(MyViewmodel))]
	public partial class MyPage : BaseView
	{
		public MyPage()
		{
			InitializeComponent();
		}
	}
}

Implementing the global App class:

Each Xamarin.Forms application contains one global App.cs class file, which is instantiated and started during App startup by the various platform-specific projects. When using MVVMbasics, this App class must be derived from the MVVMbasics.BaseApplication base class. This one itself inherits from Xamarin.Forms.Application, which means that inside your App class you can do whatever you are used to from any other Xamarin.Forms applications, e.g. override the OnSleep() and OnResume() methods.

Within the App class’ constructor, you may register all desired MVVM services to the global ServiceLocator, as is the case in all MVVMbasics applications on other platforms. The only major difference to a typical Xamarin.Forms App class is that instead of assigning the App’s startup page to the MainPage property, you call the SetStartupPage method. This method expects the App’s startup page either as type parameter (in which case it is automatically instantiated) or as parameter (if it has been instantiated already):

SetStartupPage<MyPage>();
SetStartupPage(new MyPage());

Internally, the SetStartupPage method instantiates the provided page if necessary and assigns it to the App’s MainPage property. In addition, it checks whether the MVVMbasics NavigatorService has been registered and if it contains more than one View / Viewmodel pair – in this case it can be assumed that the App shall support page navigation, and the startup page is automatically wrapped within a Xamarin.Forms.NavigationPage. This means that there is no need to manually create an instance of NavigationPage!

In summary, the full implementation of an MVVMbasics App class for Xamarin.Forms could look as follows:

public class App : BaseApplication
{
	public App()
	{
		// Services used by the application
		var navigationService = new NavigatorService();
		navigationService.RegisterAll("MyApp.Views.*");
		ServiceLocator.Register(navigationService);
		ServiceLocator.Register<MessageboxService>();

		// The root page of the application
		SetStartupPage<MyPage>();
	}
}

Permanent link to this article: http://www.mobilemotion.eu/?p=1449&lang=en

Mar 17

[MVVMbasics] Targeting the Android and iOS platforms via Xamarin.Forms #1

Notice

All blog posts with a title that starts with [MVVMbasics] are related to the MVVMbasics framework. If you are only interested in my regular blog posts and not in MVVMbasics, ignore these. To list all articles covering MVVMbasics, go to http://mvvmbasics.mobilemotion.eu/documentation!

New platforms supported by version 2.2 and higher:

Version 2.2 of the MVVMbasics framework adds functionality for creating mobile applications using the Xamarin.Forms platform. Xamarin.Forms enables the creation of native cross-platform applications for the Android, iOS and Windows Phone Silverlight platforms using C#.

With the help of MVVMbasics 2.2 or higher, implementing these Apps following the MVVM patterns is getting a lot easier. In addition, it allows to add Android and iOS support to existing Apps that are based on MVVMbasics with minimal effort: All that needs to be done is implementing platform-dependent services as well as visual pages for the Xamarin.Forms platform.

Project structure:

Xamarin.Forms solutions typically consist of three or four C# projects:

  • A platform-specific project for each target platform – iOS, Android, Windows Phone (only in Visual Studio as Windows Phone development is not supported in Xamarin Studio):
    These projects may contain artwork and platform-specific controls, but typically only one page / activity that instantiates and starts one common App class.
  • A common project that includes all files that are shared between the target platforms:
    This project contains the above-mentioned global App class, as well as any Data Models, Viewmodels, Views, Services, Converters, etc.
    This project can either be a Portable Class Library, or a Shared project. In both cases, it must be referenced by the platform-specific starter projects.

In addition to this project structure, I’d suggest to add another C# project to the solution, which would be a Portable Class Library that targets all Xamarin.Forms platforms and Windows Phone Silverlight, as well as any additional platforms you might want your App to support. In this case, this project would hold all Data Models, Viewmodel, and Service interfaces, while the Xamarin.Forms common project (the PCL or shared project mentioned in the list above) would only contain Views, Converters, and Service implementations.

This architecture allows to add platform-specific projects that target, for example, WPF or Windows Store Apps, at a later point in time. You could then re-use all the Data Models and Viewmodels on all additional platforms and need to re-implement only Views and platform-specific services.

Project setup in Visual Studio:

Project setup in Visual Studio and Xamarin Studio follows similar rules, however there are a few steps that need special attention in Xamarin Studio, therefore I’ll cover these in a separate section in the second part of this article.

In general, the simplest way of setting up an MVVMbasics application is using the MVVMbasics Project Templates which can be downloaded from Visual Studio Gallery: If you have the project templates installed as Visual Studio extension, just create a new solution of type Multi-Platform Application Core using MVVMbasics (which can be found within the Visual C# -> Multi-Platform category). The solution will contain one project which is a Portable Class Library, which will contain all your Models, Viewmodels, and Service interfaces. Then, add a new project of type Xamarin.Forms App for MVVMbasics Core project to the solution: Several projects will be created automatically, one for each target platform and one PCL that will contain all your Views and Service implementations!

If you’d like to create the project structure manually (or need to add MVVMbasics support to an existing project), simply follow these steps:

  1. If the project doesn’t exist already, create a new project in Visual Studio and choose one of the Blank App project types found in the Visual C# -> Mobile Apps category (depending on whether you like a Portable Class Library or a Shared Project as common Xamarin project), and name it like your desired application’s name:

    MVVM pattern: Hierarchy of layers 
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     

    In addition, add an additional project of type Class Library (Xamarin.Forms Portable) to the solution. I usually call this project “Core” since it will contain the core functionality for all target platforms, but you can name it whatever you want – just don’t be confused as I will refer to this project as the Core project within this article.

  2. Add a reference to the MVVMbasics framework to all those projects (even the platform-specific Android / iOS / WinPhone projects). To do so, use either the visual Nuget Package Manager or the Package Manager Console to download and install the MVVMbasics library, and make sure that version 2.2.x (or newer) has been installed. You’ll notice that two new references MVVMbasics and MVVMbasicsXF have been added to most of the projects.
  3. Add the respective Models, Viewmodels, Services, etc. namespaces to the Core project. For details about how to create the Models, Viewmodels, and Service interfaces, please refer to the MVVMbasics Documentation & Tutorials page.
    The Xamarin.Forms common project should already contain one class file App.cs. To create pages, add a new Views namespace and create at least one file of type Forms Xaml Page. For details about how to implement the App class and the pages, please see the section Implementing Views and the App class in the second part of this article!

Permanent link to this article: http://www.mobilemotion.eu/?p=1447&lang=en

Mar 16

MVVMbasics 2.2 with Xamarin.Forms support is now available

The newly released version 2.2 of the MVVMbasics frameworks adds support for the Android and iOS platforms via Xamarin.Forms. In addition, it is now possible to specify attribute-based bindable properties within Models and View Models.                                                    

Permanent link to this article: http://mvvmbasics.mobilemotion.eu

Feb 24

A smart ICommand implementation #4

In the previous blog post, we discussed an approach that allows to specify an MVVM Command’s CanExecute condition as well as the properties this condition depends on in one line, without the need of adding information about participating commands to the properties’ setter methods.

This solution improves maintainability by positioning code snippets that syntactically belong together nearby each other, but it still contains redundant code parts that are defined more than once: All of the properties that are already referenced within the CanExecute condition need to be repeated in separate fields – this can definitely be shortened!

Automatic retrieval of dependent properties:

If we can automatically retrieve a property’s name (as string value) out of an expression that defines the property (as mentioned in the previous blog post and described in detail in Thomas Mutzl’s article A smart MVVM command), why shouldn’t we be able to retrieve all referenced properties’ names directly from the Command’s CanExecute condition? This is in fact possible – let’s take a look at how to implement such an optimization:

What have we done so far? The last version of the DelegateCommand constructor presented in the previous blog post has the following signature:

public DelegateCommand(Action<object> action, Func<object, bool> condition,
		INotifyPropertyChanged viewmodel, params Expression<Func<object>>[] dependsOnProperties)

Our aim is to get rid of the dependsOnProperties parameter, so let’s omit it. Instead, we pass the condition as lambda expression:

public DelegateCommand(Action<object> action, Expression<Func<object, bool>> condition,
		INotifyPropertyChanged viewmodel)

Apart from the missing list of dependent properties, this method can be called the same way as the previous one, since syntactically there is no difference between passing a Func and an Expression, except for one case: If you didn’t specify the condition inline (as lambda expression) but in a separate method, you’ll need to convert this method call to a lambda expression, for example:

public MyViewmodel()
{
	SearchCommand = new DelegateCommand(SearchMethod, () => IsSearchAllowed());
}

private bool IsSearchAllowed()
{
	// Evaluate condition
}

However, in real life most conditions won’t be too complex and will usually depend on only one or two properties, so it should be possible to define the condition’s body as lambda expression directly within the Command’s initialization – let’s focus on this case for the moment:

public MyViewmodel()
{
	SearchCommand = new DelegateCommand(SearchMethod,
			() => IsLoggedIn && !String.IsNullOrEmpty(Keywords));
}

Of course, also the constructor’s body needs to be adapted to reflect this changed signature. We need to

  1. convert the condition that has been passed as lambda expression back to a standard Func type to be able to store it in the private _canExecute field (which the Command’s CanExecute() method depends on), and
  2. fill the list of dependent properties which, in the old version, had been passed explicitly.

The first task is easily solved by compiling the lambda expression and storing it as the global _canExecute condition:

_canExecute = canExecute.Compile();

The second task is much more complex – after all, this is what we’ve been after since the beginning: Getting rid of an explicitly passed list of dependent properties and magically retrieving them from the condition’s body! Let’s extract that logic to a separate helper method ParseExpresionTree():

private void ParseExpresionTree(Expression inputExpression, List<string> properties)

The lambda expression that represents the Command’s condition is structured as tree: It contains several other expressions that are combined with each other through operations. There exist different types of expressions – the one we’re after is MemberExpression as this one represents a call to a member, e.g. to a property (after all, this is what we’re looking for: each call to a property must be found, as we need to register to all those properties’ PropertyChanged events!).

So, if we’re dealing with a MemberExpression, check if the member that shall be called is a property, and in that case retrieve its name and store it in the global list of dependent properties:

private void ParseExpresionTree(Expression inputExpression, List<string> properties)
{
	if (inputExpression is MemberExpression)
	{
		var e = inputExpression as MemberExpression;
		var member = e.Member;
		if (member is PropertyInfo)
		{
			PropertyInfo property = member as PropertyInfo;
			Type owner = property.DeclaringType;
			if (owner.GetTypeInfo().ImplementedInterfaces.Contains(typeof(INotifyPropertyChanged)))
			{
				string propertyName = property.Name;
				if (!properties.Contains(propertyName))
					properties.Add(propertyName);
			}
		}
	}
	else
	{
		// process all other types of expressions...
	}
}

The problem is: To find those MemberExpressions, we need to parse the whole tree, and this tree will contain various other expressions that all need to be processed in a different way. For example, if the tree contains a ConditionalExpression at some position (which is an expression that represents an if block), we need to divide this part of the tree into three sub-parts:

  • the expression that shall be tested,
  • the expression that shall be invoked if the test returns true, and
  • the expression that shall be invoked if the test returns false.

Each of these three sub-parts again is represented as expression of some type, and each of those three expressions needs to be processed separately to check if one of them contains a MemberExpression – we do this by calling the ParseExpresionTree() method recursively, passing each of the three sub-expressions:

private void ParseExpresionTree(Expression inputExpression, List<string> properties)
{
	if (inputExpression is MemberExpression)
	{
		// retrieve property name as shown above
	}
	else if (inputExpression is ConditionalExpression)
	{
		var e = inputExpression as ConditionalExpression;
		ParseExpresionTree(e.Test, properties);
		ParseExpresionTree(e.IfTrue, properties);
		ParseExpresionTree(e.IfFalse, properties);
	}
	else
	{
		// process all other types of expressions...
	}
}

A list of all types of expressions defined by the .NET framework can be found at MSDN. I won’t describe how to process each of these types in detail, if you’re interested in the full code please check out my ICommand implementation (available at codeplex) that has been published as part of the MVVMbasics framework!

Any way, after traversing the full expression tree we should end up with a list containing the names of all properties that are called from within the Command’s CanExecute condition! This list can then be used within the Viewmodel’s PropertyChanged event handler to force the condition to be re-evaluated.

A few thoughts about this solution:

  • Of course, working with lambda expressions has an impact on performance. Since analyzing the expression tree is done only once during Command initialization (and not each time the Command is invoked, or the condition is re-evaluated), and since most real-life Command conditions are rather simple and depend on only one or two properties, this should not affect a project’s overall performance.

    Nevertheless, you should always take into account that more complex conditions may be necessary in certain use-cases, so it might be a good idea to provide an overload to the Command’s constructor that still accepts a list of dependent properties. This allows other developers who make use of the Command implementation to circumvent the ParseExpresionTree() method in certain cases.

  • I decided to stop walking down the expression tree whenever a separate method is called. This decision is mainly based on performance considerations: It can be assumed that CanExecute conditions that are passed as inline lambda expressions won’t be too complex and therefore can be analyzed rather quickly by traversing their expression tree, while the complexity of an external method’s body (and therefore the effort necessary for analyzing the method’s contents) cannot be estimated.

    However, it might be a good idea to at least process the expressions contained in a MethodCallExpression‘s Arguments collection, since they might contain a MemberExpression that references a property which otherwise would have been omitted. For example, the Keywords property in our sample Command declaration is only referenced once as parameter to the String.IsNullOrEmpty() method – this property would have been lost!

    Again, also because of this limitation it might be a good idea to offer an overload constructor that allows to manually specify the list of dependent properties – otherwise, it would be impossible to retrieve the dependent properties if only an external method was passed as condition.

  • Finally, this approach is rather tolerant: It might find values that are actually not referenced as properties from within the given expression. This is not a problem, since those values (although being stored in the list of dependent properties) won’t appear as PropertyChanged event args and therefore won’t ever be used for comparison.

Permanent link to this article: http://www.mobilemotion.eu/?p=1424&lang=en

Feb 20

A smart ICommand implementation #3

To avoid the drawbacks of manually querying Command conditions from within the dependent properties’ setter methods as listed in the previous post, I’d like to discuss an approach that combines all dependencies within the Command initialization. The solution presented in this article is based on Thomas Mutzl’s smart command implementation, in the following (and final) blog post I’ll suggest a further improvement of this approach.

Binding conditions to Viewmodel properties:

Basically, we’d like to get rid of the Command references within the bindable properties’ declarations. Instead of defining for each property which commands depend on it, the idea is to instruct each command on which properties it depends. The command would then register to those properties’ PropertyChanged event – this way, the command is automatically informed whenever one of the properties it depends on has changed, and it can re-evaluate its CanExecute condition.

To do so, we’d need to pass a reference to the Viewmodel as well as a list of all dependent property names to each Command during initialization – our example Command as defined in part #2 would look as follows:

public DelegateCommand SearchCommand { get; set; }
 
public MyViewmodel()
{
    SearchCommand = new DelegateCommand(SearchMethod,
            () => IsLoggedIn && !String.IsNullOrEmpty(Keywords),
			this,                                               // Reference to the Viewmodel
			"IsLoggedIn", "Keywords"                            // List of all properties the condition depends on
	);
}

private string _keywords;
public string Keywords
{
    get { return _keywords; }
    set
    {
        _keywords = value;
        RaisePropertyChanged("Keywords");
    }
}
 
private bool _isLoggedIn
public bool IsLoggedIn
{
    get { return _isLoggedIn; }
    set
    {
        _isLoggedIn = value;
        RaisePropertyChanged("IsLoggedIn");
    }
}

The Command’s constructor would register to the PropertyChanged event that is provided by the Viewmodel. Whenever this event is raised, it needs to check if the source property is included in the list of registered dependent properties, an in this case it would raise the CanExecuteChanged event to signal that the condition must be re-evaluated:

public class DelegateCommand : ICommand
{
    private readonly Action<object> _action;
  
    private readonly Func<object, bool> _condition;
	
	private readonly string[] _dependsOnProperties;
  
    public DelegateCommand(Action<object> action, Func<object, bool> condition, 
			INotifyPropertyChanged viewmodel, params string[] dependsOnProperties)
    {
        _action = action;
        _condition = condition;
		_dependsOnProperties = dependsOnProperties;
		
		viewmodel.PropertyChanged += ViewmodelPropertyChanged;
    }
	
	private void ViewmodelPropertyChanged(object sender, PropertyChangedEventArgs e)
	{
		if (_dependsOnProperties.Contains(e.PropertyName))
			RaiseCanExecuteChanged();
	}
  
    public event EventHandler CanExecuteChanged;
  
    public void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null)
            CanExecuteChanged(this, EventArgs.Empty);
    }
  
    public void Execute(object parameter)
    {
        if (CanExecute(parameter))
            _action.Invoke(parameter);
    }
  
    public bool CanExecute(object parameter)
    {
        return _condition == null || _condition.Invoke(parameter);
    }
}

The big advantage of this solution is that both the CanExecute condition itself and the properties it depends on are declared directly within the Command’s constructor – the property declarations stay clean and need not contain any information about the participating commands. Whenever a Command’s condition changes, only the Command’s constructor needs to be adapted.

Nevertheless, the presented approach still is far from perfect: For example, what’s rather annoying is that the dependent properties’ names are passed as string types – when changing some property’s name during refactoring, these values needs to be reworked manually. Instead, we could define a Command constructor that expects a list of expressions instead of string values – the constructor’s signature would then look as follows:

public DelegateCommand(Action<object> action, Func<object, bool> condition, 
			INotifyPropertyChanged viewmodel, params Expression<Func<object>>[] dependsOnProperties)

The constructor would need to retrieve each property’s name from this list of expressions to be able to store them as string values – this is necessary since we want to compare it with the property name passed by the PropertyChanged event handler, and this one still is of type string. Since we’re not done yet and I’ll present a different optimization approach shortly, I won’t go into details about this adaptation – if you’re interested in how the Command’s constructor could be implemented in detail, please check out Thomas Mutzl’s original article!

Irrespective of the decision whether we want to pass property references as expression or string value, there are still two aspects that can be improved:

  1. The fact that we need to pass this as a reference to the Viewmodel, and
  2. the fact that the list of dependent properties seems redundant, since the condition itself (which is defined in the same line of code, only a few characters to the left) basically contains the same informations.

While issue #1 (the reference to the Viewmodel via this) is mainly a personal preference, it can be changed easily, for example by creating an extension method to the INotifyPropertyChanged interface that returns a new instance of DelegateCommand

public static DelegateCommand CreateCommand(this INotifyPropertyChanged viewmodel, Action<object> action,
			Func<object, bool> condition, params string[] dependsOnProperties)

…which, at least, moves the reference to this to the beginning of the line:

public MyViewmodel()
{
    SearchCommand = this.CreateCommand(SearchMethod,
            () => IsLoggedIn && !String.IsNullOrEmpty(Keywords),
			"IsLoggedIn", "Keywords");
}

If you’re using a base Viewmodel class all Viewmodels within a project are derived from, the CreateCommand method can also be defined within this base class, in this case even this reference to the this keyword can be omitted.

Issue #2 is more relevant, as getting rid of the list of property names would help shorten the Command initialization significantly. On the other hand, it is a more complex task, which is why I’ve decided to deal with this topic in a separate blog post – if you’re interested in this final optimization step, check out part #4 of this series of articles!

Permanent link to this article: http://www.mobilemotion.eu/?p=1416&lang=en

Feb 17

A smart ICommand implementation #2

If we cannot rely on CommandManager in Windows Store Apps, as mentioned in the previous post, how can we manually re-query our Commands’ CanExecute conditions at the right point of time? This might sound more difficult as it really is in most cases. Let’s think of a real-life example to illustrate this:

Imagine a business application that includes, among others, a search function consisting of a text field for entering key words and a Search button. The user may only click the Search button is he or she is logged in and if some key words have been entered in the designated text field. Both login status and key words will already be represented in the Viewmodel, e.g. the text field’s content might be binding to a string property:

private string _keywords;
public string Keywords
{
	get { return _keywords; }
	set
	{
		_keywords = value;
		RaisePropertyChanged("Keywords");
	}
}

private bool _isLoggedIn
public bool IsLoggedIn
{
	get { return _isLoggedIn; }
	set
	{
		_isLoggedIn = value;
		RaisePropertyChanged("IsLoggedIn");
	}
}

Note that for simplicity reasons I use short bindable property declarations that do not check if the value has changed in the setter. In practice, you might want to use one of the convenience methods discussed in An elegant INotifyPropertyChanged implementation.

In addition, the Search button is binding to a Command that is defined using the DelegateCommand presented in the first part of this series of articles. This one specifies a condition to indicate that is shall only be active if the user is logged in and if the Keywords property contains values:

public DelegateCommand SearchCommand { get; set; }

public MyViewmodel()
{
	SearchCommand = new DelegateCommand(SearchMethod, 
			() => IsLoggedIn && !String.IsNullOrEmpty(Keywords));
}

Querying CanExecute conditions manually:

Since the SearchCommand‘s condition is based on the Keywords and IsLoggedIn properties, whenever one of those two properties changes we need to inform the View that the Command’s condition must be re-evaluated. Fortunately, the ICommand interface defines the CanExecuteChanged event which any View can register to, so we just need to raise this event. The DelegateCommand already contains a convenience method RaiseCanExecuteChanged() that checks for null and raises this event, so we can just call this method in each property’s setter:

private string _keywords;
public string Keywords
{
	get { return _keywords; }
	set
	{
		_keywords = value;
		RaisePropertyChanged("Keywords");
		SearchCommand.RaiseCanExecuteChanged();
	}
}

private bool _isLoggedIn
public bool IsLoggedIn
{
	get { return _isLoggedIn; }
	set
	{
		_isLoggedIn = value;
		RaisePropertyChanged("IsLoggedIn");
		SearchCommand.RaiseCanExecuteChanged();
	}
}

If we declare bindable properties using the custom Set() convenience method as suggested in An elegant INotifyPropertyChanged implementation #4, we could of course create an overload of this method that accepts a list of all Commands that depend on a certain property. The Set() method would then call RaiseCanExecuteChanged() on all those commands, and we could shorten the property declarations to something like the following:

private string _keywords;
public string Keywords
{
	get { return _keywords; }
	set { Set(ref _keywords, value, "Keywords", CreateCommand); }
}

private bool _isLoggedIn
public bool IsLoggedIn
{
	get { return _isLoggedIn; }
	set { Set(ref _isLoggedIn, value, "IsLoggedIn", CreateCommand); }
}

This approach basically has two disadvantages:

  • Since several commands might depend on one property, we’d need to add a params ICommand[] commands parameter to the Set() method. This, however, does not work in combination with the [CallerMemberName] attribute that is already present in the Set method’s signature, because both need to be specified as the last parameter. Therefore, as you can see in the example snippet above, we’d need to specify the property name as string which brings about subsequent problems, as discussed in An elegant INotifyPropertyChanged implementation #2.
  • In addition, it’s not easily maintainable: Whenever some Command’s condition changes, we need to browse through the declarations of all properties that are referenced in the condition, and ensure that each property’s setter includes a call to the Command’s RaiseCanExecuteChanged method.

There is in fact another approach that solves both problems by declaring all property dependencies directly within the Command’s initialization. A detailed explanation will follow in part #3!

Permanent link to this article: http://www.mobilemotion.eu/?p=1411&lang=en

Feb 13

A smart ICommand implementation #1

In my series of blog posts covering the very basics of MVVM, I presented a basic MVVM Command. At first sight, there’s not much to discuss: As the .NET ICommand interface (and its two methods Execute and CanExecute) suggests, Commands basically have two purposes:

  • Each command contains an action that it executes on request.
  • In addition, it may contain a condition that must be fulfilled for the specified action to be carried out.

The simplest command implementing the ICommand interface would look like the following:

public class DelegateCommand : ICommand
{
    private readonly Action<object> _action;
 
    private readonly Func<object, bool> _condition;
 
    public DelegateCommand(Action<object> action, Func<object, bool> condition)
    {
        _action = action;
        _condition = condition;
    }
 
    public void Execute(object parameter)
    {
		if (CanExecute(parameter))
			_action.Invoke(parameter);
    }
 
    public bool CanExecute(object parameter)
    {
        return _condition == null || _condition.Invoke(parameter);
    }
 
    public event EventHandler CanExecuteChanged;
 
    public void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null)
            CanExecuteChanged(this, EventArgs.Empty);
    }
}

Note that this basic implementation also allows the creation of Commands that don’t expect parameters, as well as Commands that don’t specifiy a condition for the action to be executed, by passing null to either the parameter or the condition argument. In a production environment, you might want to add constructor overloads to do so, but I’ll omit those in this article for the sake of simplicity.

As can be seen in the code snippet above, both the action to be executed and the condition are typically passed to the Command as constructor parameters. Executing the specified action is not that thrilling since it won’t change during runtime, however the condition is a bit more tricky since its result may of course change and therefore needs to be re-evaluated under certain conditions.

In any case, the condition should be evaluated before executing the action. However, UI frameworks such as WPF visualize a Command’s CanExecute condition by enabling or disabling the user control that is bound to the Command. If a Button binds to a Command whose condition evaluates to false, for example, the button will be drawn as inactive and can’t be clicked by the user. This means that CanExecute conditions should be re-evaluated regularly. In this series of articles, I’d like to present and discuss various ways of updating MVVM Commands’ conditions.

Auto-updating conditions:

WPF features a global CommandManager class. This one keeps track of an application’s Commands and automatically re-evaluates their CanExecute conditions on certain occasions, e.g. when input focus switches from one control to another, when a list’s selected item changes, etc. In addition, you can also force it to re-query all Commands’ conditions by calling the CommandManager.InvalidateRequerySuggested() method.

There are only two drawbacks of relying on the CommandManager, of which the first one is easily solved while the second one might be a blocker for certain scenarios:

  • Out of the box, CommandManager is only aware of all routed commands existing in an application, therefore it updates only their conditions. When we’re implementing our own delegate commands (e.g., by using the code snippet posted above), we need to inform WPF that our custom command exists. This can be done easily by hooking our command’s CanExecuteChanged event to the CommandManager’s RequerySuggested event, such that every time it evaluates all routed commands, also our Command’s condition is re-queried:

    public event EventHandler CanExecuteChanged
    {
    	add { CommandManager.RequerySuggested += value; }
    	remove { CommandManager.RequerySuggested -= value; }
    }
    
  • The second (and more serious) drawback is the fact that the CommandManager class is only available in WPF, not in Silverlight (as far as I know, although there are a few custom implementations out there) and certainly not for WinRT. While this is not a problem for WPF-only applications, it makes cross-platform implementations (which is one of the big advantages of the MVVM pattern in general) impossible.

    So, what can we use as an alternative solution for re-evaluating CanExecute conditions on a regular basis? There are a few strategies that allow cross-platform Commands, read on about it in the second part of this series!

Permanent link to this article: http://www.mobilemotion.eu/?p=1385&lang=en

Older posts «