How to implement INotifyPropertyChanged without strings and support Asynchronous Notification

In this post I want to show you an alternative way of implementing INotifyPropertyChanged with a nice, string-less way of raising the PropertyChanged event.

It implements usual INotifyPropertyChanged infrastructure and allows you to have strongly-typed property notifications (instead of mangling with strings). Also because PropertyChanged event can be raised from asynchronous code (ie raised from different thread than main) it needs to be dispatched to the main thread which is done by using simple utility class Call and it’s OnUIThread() routine.

For example in your ViewModel you want to create a property call “MyProp”, and on line 12 instead of using a literal string you now use a strongly type property with intellisense support from Visual Studio:

    public class MyViewModel : ViewModelBase
    {
        private string myProp;
        public string MyProp
        {
            get { return myProp; }
            set
            {
                if (this.myProp != value)
                {
                    myProp = value;
                    NotifyOfPropertyChange(() => MyProp);
                }
            }
        }
    }

First, you create a base class ViewModelBase.cs like this:

public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        public void NotifyOfPropertyChange(string propertyName)
        {
            Call.OnUIThread(() => PropertyChanged(this, new PropertyChangedEventArgs(propertyName)));
        }

        public void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property)
        {
            var lambda = (LambdaExpression)property;

            MemberExpression memberExpression;
            if (lambda.Body is UnaryExpression)
            {
                var unaryExpression = (UnaryExpression)lambda.Body;
                memberExpression = (MemberExpression)unaryExpression.Operand;
            }
            else
            {
                memberExpression = (MemberExpression)lambda.Body;
            }

            NotifyOfPropertyChange(memberExpression.Member.Name);
        }
    }

plus a helper class Call.cs that:

    public static class Call
    {
        public static void OnUIThread(Action action)
        {
            Dispatcher dispatcher = Deployment.Current.Dispatcher;

            if (dispatcher.CheckAccess())
            {
                action();
                return;
            }

            dispatcher.BeginInvoke(action);
        }
    }

Using VisualStateManager/Storyboard in MVVM

A recurring problem with MVVM is how to incorporate animations in a nice MVVM way. The problem is that StoryBoards need to be started from the view, since they are usually configured in XAML. This means that the ViewModel needs a reference to the view, in order to tell it when the animation should start. Keeping a reference from the ViewModel to the View is obviously “not done” in the MVVM pattern. In this post I’m going to show how you can use the VisualStateManager to start animations and incorporate it in the MVVM pattern, without keeping a reference from the ViewModel to the View.

1st a create VisualStates.cs class which implement an attached property

    public static class VisualStates
    {
       public static readonly DependencyProperty CurrentStateProperty =
           DependencyProperty.RegisterAttached("CurrentState", typeof(String), typeof(VisualStates), new PropertyMetadata(TransitionToState));

        public static string GetCurrentState(DependencyObject obj)
        {
            return (string)obj.GetValue(CurrentStateProperty);
        }

        public static void SetCurrentState(DependencyObject obj, string value)
        {
            obj.SetValue(CurrentStateProperty, value);
        }

        private static void TransitionToState(object sender, DependencyPropertyChangedEventArgs args)
        {
            Control c = sender as Control;
            if(c != null)
            {
                VisualStateManager.GoToState(c, (string)args.NewValue, true);
            }
            else
            {
                throw new ArgumentException("CurrentState is only supported on the Control type");
            }
        }
    }

2nd in the ViewModel provide a Property that will fire and NotifyPropertyChanged event

        private string _currentState;
        public string CurrentState
        {
            get
            {
                return _currentState;
            }
            set
            {
                if (value != _currentState)
                {
                    _currentState = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("CurrentState"));
                }
            }
        }

Finally in the View, attached VisualStates to the UserControl and Bind the Property in the ViewModel that will cause the change in Visual State

<UserControl
    ...
    xmlns:mvvm="clr-namespace:MVVMSupport;assembly=MVVMSupport"
    DataContext="{StaticResource mainPageViewModel}"
    mvvm:VisualStates.CurrentState="{Binding CurrentState}"
    >
    <Grid x:Name="LayoutRoot" Background="White">
    	<VisualStateManager.VisualStateGroups>
    		<VisualStateGroup x:Name="States">
                    ...

Via http://blogs.infosupport.com/blogs/alexb/archive/2010/04/02/silverlight-4-using-the-visualstatemanager-for-state-animations-with-mvvm.aspx

An alternative without using Attached Property is using Blend 4’s PropertyChangedTrigger or DataTrigger

  • PropertyChangedTrigger will fire whenever there is a change in value
  • DataTrigger allow you to specify a condition and it will fire only when the condition matches

Handling and Troubleshooting WCF Faults in Silverlight

image

Shows you how to identfy the problems with your WCF services and how to fix them. He covers several topics including these:

  • Handling Faults: How to get exceptions propogated from the sderver to Silverlight e.g. using FaultBehavior (more detail about FaultBehavior go here @msdn)
  • How to use Fiddler to use with WCF  – replace localhost with ipv4.fiddler in SerivceReference.ClientConfig and Browser’s address bar
  • Using the new relative address feature in Silverlight 4’s ServiceReference.Clientconfig e.g. ..\xyz.svc

Via http://channel9.msdn.com/Shows/SilverlightTV/Silverlight-TV-46-Whats-Wrong-with-my-WCF-Service

GPS Simulator for Windows Phone 7

image

You want to develop applications that use the GPS on your Windows Phone 7.  You may not have a physical device.  Or even if you do, sometimes it’s not very convenient to test out your GPS based software by walking around with your phone.  To help out with this type of development, here is a very simple and crude GPS Simulator to use in your WP7 apps.  There are two components to the simulator, the first is a Silverlight desktop hack job application that can be used to construct your route and sample data points.  The second is a class that you include in your WP7 app called FakeGps .

continue @ http://new.efficientcoder.net/2010/09/gps-simulator-for-windows-phone-7.html

A guide to cleaner XAML with custom namespaces and prefixes

Before:

   <UserControl x:Class="Sandworks.Silverlight.NamespaceExample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:my="clr-namespace:Sandworks.Silverlight.NamespaceExample.Controls"
    xmlns:conv="clr-namespace:Sandworks.Silverlight.NamespaceExample.Converters"
    xmlns:lib="clr-namespace:Sandworks.Silverlight.NamespaceExample.ClassLibrary.Converters;assembly=Sandworks.Silverlight.NamespaceExample.ClassLibrary" >  

After:

   <UserControl x:Class="Sandworks.Silverlight.NamespaceExample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:sw="http://schemas.sandworks.com/sl/" > 

consolidated into 1 line xmlns:sw=…

To achieve this behavior you need to follow the next steps:

  1. Go to the project where you want to map CLR namespaces to a custom namespace.
  2. Open AssemblyInfo.cs under Properties
  3. Add the following to the top of your code: using System.Windows.Markup;
  4. Add the XmlnsPrefix and XmlnsDefinition attributes.

Example:

[assembly: XmlnsPrefix("http://schemas.sandworks.com/sl/", "sw")]
[assembly: XmlnsDefinition("http://schemas.sandworks.com/sl/", "Sandworks.Silverlight.NoNamespaceExample.Controls")]
[assembly: XmlnsDefinition("http://schemas.sandworks.com/sl/", "Sandworks.Silverlight.NoNamespaceExample.Converters")]
 

via http://www.codeproject.com/KB/silverlight/xaml_custom_namespaces.aspx

Progress Bar performance note

image

And yet another reminder: if you are using the indeterminate ProgressBar built into the Windows Phone platform, please follow this instructions to make sure you have a smooth, fluid user interface experience. You need to use a special workaround to offload the animations to the compositor thread and remember to toggle IsIndeterminate property back to false when you no longer need it.

This is super important because so many applications are doing potentially heavy processing when they are showing a progress bar like this. The performance issue is not evident in the emulator as much as on actual Windows Phone 7 devices by the way.