INotifyPropertyChanged… I am fed up of handling events just to know when a property changed

The INotifyPropertyChanged is what tells the WPF/SL binding that a property changed and that the binding should be updated. For this purpose its quite good. But what many times we end up doing is; handling the PropertyChanged in code so that we get notified that a property changed. An example is a ViewModel that need to know when a property in the underlying model changed and if it did it will do something to facilitate the View.

Doing this in code is a bit ugly because you base everything on “magic strings”.. something like this

image

Another problem is that if you use an anonymous delegate you need to do loads of tricks in order to unregister to the event.

In order to over come this I created a PropertyObserver that handles these 2 issues. (Please note that there are already others, Philip Sumi has a good one here and  Josh Smith has a good one here. I created my own since I wanted to have extra + different way of doing it). Also this problem can be solved easily using Rx, I am doing this sample so that you do not need to depend on Rx.

The implementation I did is very simple, I created a PropertyObserver class that uses lambdas so that you tell it what property you want to subscribe to and pass an action to do your “Property Changed handling”. What I also did is an attached method so that all objects that implement INotifyPropertyChanged can simple handle the property changed… so the code looks like this

image

One would ask and how do I unregister? is this using weak event pattern? The answer is NO. I wanted to keep it simple and cross platform (for WPF and SL). what you can do is a more Rx approach… basically in RX if you subscibe to something you get an IDisposable in return so that you can Dispose (i.e in our case unsubscribe) when you want like this

image

as you can see here I am wrapping the call in a using statement… but if you need to unsubscribe in any specific state you can store the IDisposable that you get from the Do call and call Dispose to unsubscribe.

Many times you need this for only one time i.e a property changes you do something and you do not want to get called any more times. For this I created a DoOnce. This will unsubscribe for you once the property changes once. The API is very similar and looks like this

image

That’s more or less it.

Big thanks go to Diego Colombo and John Rayner (two champs that work with me) for the help and input they gave me on this :) You rock guys!

You can download the code here.

OR if you have MEFedMVVM download the latest version since its in MEFedMVVM.

MEFedMVVM: Testability

>> If you are new to MEFedMVVM, I suggest you first read this article to get started: http://marlongrech.wordpress.com/2010/05/23/mefedmvvm-v1-0-explained/

Having solid unit tests is key to have successful projects. When these projects get really large and especially if there are several developers on the project. Once you get used to unit testing you feel un-complete if you do not unit test your code. One of the virtues of the Art of Unit testing is Mocking. Mocking is really important while you are unit testing so you remove all the dependencies of the code you are testing and you just test what you really want to test.

“Testability” is something that I take very seriously and in MEFedMVVM it was no exception.

Unit testing best friend is Dependency Injection(since with this you can mock all the dependencies); MEFedMVVM leverages MEF thus this comes for free. Having said that what is also really cool with MEFedMVVM is that all services exposed can be mocked. By services I do not just mean backend services (example a service that connects to a DB to load data) but also UI services (or as I usually refer to them MEFedMVVM IContextAware services).

Here is a sample unit test (you can see this in the source code of MEFedMVVM) Please note I am using Rhino Mocks as my mocking framework for this sample.

 

image

As you can see in this test I am testing that when I set the SelectedUser property on the ViewModel (which would be updated by binding at runtime) I send a mediator message. I can do this because the Mediator that comes out of the box with MEFedMVVM is exposed as an IMediator thus I can easily mock it and test that I am doing the right calls to the Mediator.

What is really cool is that I can even mock behaviours like ViewModel setting a Visual State or even testing that on Loaded event of the View the ViewModel does something (in my case it will load some data from a service)

image

As you can see in the above code, I am testing that when the ContainerLoaded event (which is an event in the MEFedMVVM IContainerStatus an IContextAware service that abstracts the Loaded and unloaded event of the View) of the IContainerStatus is raised, I am setting the “Welcome” state via the IVisualStateManager ( which is another MEFedMVVM IContextAware service that lets you set a specific VisualState on the View).

I am also testing that the first user is selected by default and that my data is loaded.

Conclusion

I think the fact that I can mock any dependency that my ViewModel has (even if it is a “UI” thing) is a really powerful thing! Currently MEFedMVVM is helping me and my team a lot and we are finding that Unit Testing with MEFedMVVM is really awesome. Having said that if you have any comments/suggestion on how to make testing easier with this library, Please do let me know.

Thanks

Download MEFedMVVM

http://mefedmvvm.codeplex.com/

Working with the WPF VSM in an MVVM friendly manner

Lately I have been working a lot with Silverlight. While working on my first Silverlight project I encountered my first problem… There are no Triggers in SL!!! At first I was frustrated and started hitting my self in the head but hey SL is not that bad… SL has the Visual State Manager aka VSM which is a pretty awesome tool I must say. I still think SL should have Triggers for some tasks such as ControlTemplates and other tasks yet with VSM you can still get some cool stuff done :)

What really strikes me with the VSM is the way it is supported in Blend, and YES designers love VSM! With the VSM they can define states in an easy way (and yes these states transition and the designer has full control on the transitions done). They can navigate easily through states in Blend and even see the transitions being done in Blend there and then.

image

Going back to WPF one thing that is missing in WPF is a way how a designer can define animations that get Triggered when something happens… Or let me re phrase that…. There is no easy way, or better not as easy as the VSM :)

Triggers in WPF can invoke Storyboards yet still it feels like the WPF animation system does not have a nice way to dispatch animations… Enter the VSM for WPF.

Yes, VSM is available for WPF as well, and yes it is supported in Blend (you just have to do a little trick that you can find over here)

I created a sample project that leverages the VSM for its animations and yes its all MVVM (in the sample app you’ll see that I am also using design time data for blend and I also included a mini MVVM Libarary that I use to develop my everyday WPF projects :) ).

 

Let’s Get Started

So let’s start by defining a state in Blend. In order to do so (assuming you followed the instructions to enable the VSM for WPF projects) you need to navigate to the States Tab and create a new state. Once the state is created and selected you’ll see that Blend will go to recording mode (just like it does when you are doing a normal WPF animation). Now you can change any property of any element and the Blend will record that and create the appropriate transitions for it.

image

Ok, now that we have the states defined in Blend what is next? well we need a way how to invoke these states for starters!

The Blend team were so kind to give us a Behavior called GoToStateAction. This behavior will basically invoke a state when an event is raised, for example if you have a button that should dispatch a new state, you simple find the GoToStateAction form the Asset tab and drag it on the button

image

Then you can set the properties for this behavior in the properties tab. There you can specify which state to select.

image

By doing these steps (define a state and use the GoToStateAction to invoke the state) you are already good to go. You can press F5 and you can see that when you click the button you get transitioned from one state to another. (P.S it’s important that you set a default transition time span otherwise you end up with no transition since the default is 0s).

 

This is all cool but what about MVVM ??

I hear you I hear you…. What if I have a ViewModel which needs to invoke a state change ?? Unfortunately this is not so straight forward… BUT of course there is a solution… I extended the GoToStateAction so that it can be hooked up from a ViewModel. Here is my extended version

   1: public class VisualStateManagerInvoker : GoToStateAction

   2: {

   3:     #region CurrentState

   4:  

   5:     /// <summary>

   6:     /// CurrentState Attached Dependency Property

   7:     /// </summary>

   8:     public static readonly DependencyProperty CurrentStateProperty =

   9:         DependencyProperty.RegisterAttached("CurrentState", typeof(string), typeof(VisualStateManagerInvoker),

  10:                                             new PropertyMetadata((string)null,

  11:                                                                  new PropertyChangedCallback(OnCurrentStateChanged)));

  12:  

  13:     /// <summary>

  14:     /// Gets the CurrentState property.  This dependency property 

  15:     /// indicates ....

  16:     /// </summary>

  17:     public static string GetCurrentState(DependencyObject d)

  18:     {

  19:         return (string)d.GetValue(CurrentStateProperty);

  20:     }

  21:  

  22:     /// <summary>

  23:     /// Sets the CurrentState property.  This dependency property 

  24:     /// indicates ....

  25:     /// </summary>

  26:     public static void SetCurrentState(DependencyObject d, string value)

  27:     {

  28:         d.SetValue(CurrentStateProperty, value);

  29:     }

  30:  

  31:     /// <summary>

  32:     /// Handles changes to the CurrentState property.

  33:     /// </summary>

  34:     private static void OnCurrentStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

  35:     {

  36:         if (GetGoToStateAction(d) == null)

  37:         {

  38:             var command = new RelayCommand(x => //where x is the state name passed as parameter

  39:             {

  40:                 var stateAction = new VisualStateManagerInvoker();

  41:                 stateAction.Attach(d);

  42:                 stateAction.UseTransitions = GetShouldUseTransition(d);

  43:                 stateAction.StateName = (string)x;

  44:                 stateAction.Invoke(null);

  45:             });

  46:             SetGoToStateAction(d, command);

  47:         }

  48:     }

  49:  

  50:     #endregion

  51:  

  52:     #region GoToStateAction

  53:  

  54:     /// <summary>

  55:     /// GoToStateAction Attached Dependency Property

  56:     /// </summary>

  57:     public static readonly DependencyProperty GoToStateActionProperty =

  58:         DependencyProperty.RegisterAttached("GoToStateAction", typeof(ICommand), typeof(VisualStateManagerInvoker),

  59:                                             new PropertyMetadata((ICommand)null));

  60:  

  61:     /// <summary>

  62:     /// Gets the GoToStateAction property.  This dependency property 

  63:     /// indicates ....

  64:     /// </summary>

  65:     public static ICommand GetGoToStateAction(DependencyObject d)

  66:     {

  67:         return (ICommand)d.GetValue(GoToStateActionProperty);

  68:     }

  69:  

  70:     /// <summary>

  71:     /// Sets the GoToStateAction property.  This dependency property 

  72:     /// indicates ....

  73:     /// </summary>

  74:     public static void SetGoToStateAction(DependencyObject d, ICommand value)

  75:     {

  76:         d.SetValue(GoToStateActionProperty, value);

  77:     }

  78:  

  79:     #endregion

  80:  

  81:     #region ShouldUseTransition

  82:  

  83:     /// <summary>

  84:     /// ShouldUseTransition Attached Dependency Property

  85:     /// </summary>

  86:     public static readonly DependencyProperty ShouldUseTransitionProperty =

  87:         DependencyProperty.RegisterAttached("ShouldUseTransition", typeof(bool), typeof(VisualStateManagerInvoker),

  88:                                             new PropertyMetadata((bool)true));

  89:  

  90:     /// <summary>

  91:     /// Gets the ShouldUseTransition property.  This dependency property 

  92:     /// indicates ....

  93:     /// </summary>

  94:     public static bool GetShouldUseTransition(DependencyObject d)

  95:     {

  96:         return (bool)d.GetValue(ShouldUseTransitionProperty);

  97:     }

  98:  

  99:     /// <summary>

 100:     /// Sets the ShouldUseTransition property.  This dependency property 

 101:     /// indicates ....

 102:     /// </summary>

 103:     public static void SetShouldUseTransition(DependencyObject d, bool value)

 104:     {

 105:         d.SetValue(ShouldUseTransitionProperty, value);

 106:     }

 107:  

 108:     #endregion

 109:  

 110: }

This class contains 2 attached properties CurrentState (which is a string) and a GoToStateAction which is an ICommand (It also has another property ShouldUseTransition which instructs the VSM weather to use transitions or just change the properties for the new state).

The CurrentState property will attach itself to the DepenedencyObject which is being decorated with this property and hook to its VSM (please note that the attach will crawl up the Logical Tree to find the first available VSM). This operation creates an RelayCommand that is set in the GoToStateAction attached property.

Now the interesting part happens. I created a base class for ViewModels that want to invoke states called StateBaseViewModel. Here is the code…

   1: /// <summary>

   2: /// Base view model that has a property for state changes

   3: /// </summary>

   4: public class StateBaseViewModel : BaseViewModel

   5: {

   6:     private string currentState;

   7:  

   8:     /// <summary>

   9:     /// Gets or sets the current state of the ViewModel

  10:     /// </summary>

  11:     public string CurrentState

  12:     {

  13:         get { return currentState; }

  14:         set

  15:         {

  16:             currentState = value;

  17:             RaisePropertyChanged("CurrentState");

  18:         }

  19:     }

  20:  

  21:     /// <summary>

  22:     /// Changes the CurrentState property to the spcified state

  23:     /// </summary>

  24:     public ICommand GoToStateCommand { get; protected set; }

  25:  

  26:  

  27:     /// <summary>

  28:     /// Specify a command to be fired when state changes

  29:     /// </summary>

  30:     public ICommand OnGoToState { get; set; }

  31:  

  32:  

  33:     public StateBaseViewModel()

  34:     {

  35:         GoToStateCommand = new RelayCommand(

  36:             x =>

  37:             {

  38:                 CurrentState = (string)x;

  39:                 if (OnGoToState != null && OnGoToState.CanExecute(CurrentState))

  40:                     OnGoToState.Execute(CurrentState);

  41:             },

  42:             x => !String.IsNullOrEmpty((string)x)

  43:             );

  44:     }

  45: }

This base view model has the same 2 properties of the VisualStateManagerInvoker. We can make these 2 in sync together by using standard TwoWay databinding. By doing so the VisualStateManagerInvoker will feed the View Model with a command that is hooked up to a UI element VSM and when invoked this will ask the VSM for that element to transition to the state passed as parameter.

Here is the binding for this

   1: <local:Checkout  

   2:     mvvmStateManagement:VisualStateManagerInvoker.CurrentState="{Binding CurrentState}"

   3:     mvvmStateManagement:VisualStateManagerInvoker.GoToStateAction="{Binding OnGoToState, Mode=TwoWay}" />

Assuming that the element local:Checkout has a datacontext set to a view model that is inheriting from StateBaseViewModel, you can see how the VisualStateManagerInvoker is feeding this View model a GoToStateAction by simple two way databinding.

Since this command is now ready to be used from our ViewModel we can invoke a state by simple executing the command like so.

   1: CancelCommand = new RelayCommand(x =>

   2:                 {

   3:                     GoToStateCommand.Execute("CancelState");

   4:                 });

This is super awesome isn’t it :)

Another cool thing about this is that you can use this trick so that you can invoke a state from a child to its parent. Lets say that you have a Window that contains a usercontrol (which has a StateBaseViewModel set as its datacontext) and a button. You want the button to show the UserControl. Ok easy Just drag and drop a GoToStateAction behavior and set its state to the state which makes the user control visible. But now lets say you have a button inside the user control and this button needs to invoke a state defined in the Window. The VSM works with namescopes thus you cannot invoke a state that is out of your namescope. BUT with the approach of uses VisualStateManagerInvoker we can do this since we can set the binding in the same XAML line that declares the usercontrol in the Window thus being in the same namescope as the Window :) We can then make a normal command that executes the GoToStateCommand in out StateBaseViewModel (this example is in the sample application to Cancel the check out of the shopping list and to show the thank you message when someone checks out the shopping cart)

Please note that the same code works for Silverlight.

Conclusion

I think that by using VSM one makes the Developer Designer workflow a happier thing. Designers love VSM and I learnt to love it as well. Now that I can invoke states easily from my ViewModel. Besides that since the implementation gets the VSM instance in an attached behavior and then feeds it to the ViewModel via databinding, the ViewModel never touches the VSM thus unit testing is much easier like this.

I found this way of working with the VSM awesome… OK I still need to make it cooler but as it is right now you can just grab the code and start working without any problems…. hope it helps :D

 

Download sample application (P.S Open this in Blend 3 to get maximum pleasure :) )

(Sample application contains MVVMHelper a small library I built for MVVM. It contains loads of goodies… have a look and enjoy)

How to set WPF ScrollViewer VerticalOffset and Horizontal offset

Today I needed to bind to the ScrolViewer VerticalOffset and Horizontal offset to do an animation for them. Yet unfortunately you cannot do this. In order to set these properties you need to use the ScrollToVerticalOffset or ScrollToHorizontalOffset methods :S This is not very good because it means you cannot do DataBinding or animate these properties….

Well as usual I resorted to  Attached Behaviour. Basically I created 2 attached properties one for HorizontalOffset and one for VerticalOffset. These properties just call the methods ScrollToVerticalOffset or ScrollToHorizontalOffset inside the property changed handlers… yep it’s as simple as that… Here is the attached behaviour class

   1: public class ScrollViewerUtilities

   2: {

   3:     #region HorizontalOffset

   4:  

   5:     /// <summary>

   6:     /// HorizontalOffset Attached Dependency Property

   7:     /// </summary>

   8:     public static readonly DependencyProperty HorizontalOffsetProperty =

   9:         DependencyProperty.RegisterAttached("HorizontalOffset", typeof(double), typeof(ScrollViewerUtilities),

  10:             new FrameworkPropertyMetadata((double)0.0,

  11:                 new PropertyChangedCallback(OnHorizontalOffsetChanged)));

  12:  

  13:     /// <summary>

  14:     /// Gets the HorizontalOffset property.  This dependency property 

  15:     /// indicates ....

  16:     /// </summary>

  17:     public static double GetHorizontalOffset(DependencyObject d)

  18:     {

  19:         return (double)d.GetValue(HorizontalOffsetProperty);

  20:     }

  21:  

  22:     /// <summary>

  23:     /// Sets the HorizontalOffset property.  This dependency property 

  24:     /// indicates ....

  25:     /// </summary>

  26:     public static void SetHorizontalOffset(DependencyObject d, double value)

  27:     {

  28:         d.SetValue(HorizontalOffsetProperty, value);

  29:     }

  30:  

  31:     /// <summary>

  32:     /// Handles changes to the HorizontalOffset property.

  33:     /// </summary>

  34:     private static void OnHorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

  35:     {

  36:         var viewer = (ScrollViewer)d;

  37:         viewer.ScrollToHorizontalOffset((double)e.NewValue);

  38:     }

  39:  

  40:     #endregion

  41:  

  42:     #region VerticalOffset

  43:  

  44:     /// <summary>

  45:     /// VerticalOffset Attached Dependency Property

  46:     /// </summary>

  47:     public static readonly DependencyProperty VerticalOffsetProperty =

  48:         DependencyProperty.RegisterAttached("VerticalOffset", typeof(double), typeof(ScrollViewerUtilities),

  49:             new FrameworkPropertyMetadata((double)0.0,

  50:                 new PropertyChangedCallback(OnVerticalOffsetChanged)));

  51:  

  52:     /// <summary>

  53:     /// Gets the VerticalOffset property.  This dependency property 

  54:     /// indicates ....

  55:     /// </summary>

  56:     public static double GetVerticalOffset(DependencyObject d)

  57:     {

  58:         return (double)d.GetValue(VerticalOffsetProperty);

  59:     }

  60:  

  61:     /// <summary>

  62:     /// Sets the VerticalOffset property.  This dependency property 

  63:     /// indicates ....

  64:     /// </summary>

  65:     public static void SetVerticalOffset(DependencyObject d, double value)

  66:     {

  67:         d.SetValue(VerticalOffsetProperty, value);

  68:     }

  69:  

  70:     /// <summary>

  71:     /// Handles changes to the VerticalOffset property.

  72:     /// </summary>

  73:     private static void OnVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

  74:     {

  75:         var viewer = (ScrollViewer)d;

  76:         viewer.ScrollToVerticalOffset((double)e.NewValue);

  77:     }

  78:  

  79:     #endregion

  80:  

  81: }

and here is XAMl of how I use this

   1: <Grid>

   2:     <Grid.RowDefinitions>

   3:         <RowDefinition />

   4:         <RowDefinition Height="100"/>

   5:     </Grid.RowDefinitions>

   6:     <ScrollViewer x:Name="scrollViewer" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible"  >

   7:         <Border Width="9000" Height="9000"/> 

   8:     </ScrollViewer>

   9:     

  10:     <StackPanel Grid.Row="1">

  11:         <WrapPanel>

  12:             <TextBlock Text="Slider for horizontal: Value:" Margin="0,0,10,0"/>    

  13:             <TextBlock Text="{Binding ElementName=scrollViewer, Path=HorizontalOffset}"/>

  14:         </WrapPanel>

  15:         <Slider Value="{Binding ElementName=scrollViewer, Path=(local:ScrollViewerUtilities.HorizontalOffset)}" 

  16:                 Minimum="0" Maximum="9000"/>

  17:         <WrapPanel>

  18:             <TextBlock Text="Slider for vertical: Value:" Margin="0,0,10,0"/>

  19:             <TextBlock Text="{Binding ElementName=scrollViewer, Path=VerticalOffset}"/>

  20:         </WrapPanel>

  21:         <Slider Value="{Binding ElementName=scrollViewer, Path=(local:ScrollViewerUtilities.VerticalOffset)}" 

  22:                 Minimum="0" Maximum="9000"/>

  23:         

  24:         <WrapPanel>

  25:             <TextBlock Text="Animate scroll" Margin="0,0,10,0"/>

  26:             <Button Content="Do it">

  27:                 <Button.Triggers>

  28:                     <EventTrigger RoutedEvent="Button.Click">

  29:                         <BeginStoryboard>

  30:                             <Storyboard>

  31:                                 <DoubleAnimation Storyboard.TargetName="scrollViewer" 

  32:                                          Storyboard.TargetProperty="(local:ScrollViewerUtilities.VerticalOffset)"

  33:                                          Duration="0:0:1" DecelerationRatio="1.0" To="8000"/>

  34:                             </Storyboard>

  35:                         </BeginStoryboard>

  36:                     </EventTrigger>

  37:                 </Button.Triggers>

  38:             </Button>

  39:         </WrapPanel>

  40:     </StackPanel>

  41: </Grid>

Download the sample app I built for this…

Animating width and height when they are Double.NaN

A common problem in WPF when doing animation to width and height is that you cannot animate these properties (or any other properties of type double) if they are by default unset.

Here is a snippet that shows the code that would raise this kind of exception

   1: <Border Background="Red" HorizontalAlignment="Center" VerticalAlignment="Center">

   2:    <TextBlock Text="CLICK ME" VerticalAlignment="Center" HorizontalAlignment="Center"/>

   3:    <Border.Triggers>

   4:        <EventTrigger RoutedEvent="UIElement.MouseDown">

   5:            <BeginStoryboard>

   6:                <Storyboard>

   7:                    <DoubleAnimation Storyboard.TargetProperty="Height" To="300"/>

   8:                </Storyboard>

   9:            </BeginStoryboard>

  10:        </EventTrigger>

  11:    </Border.Triggers>

  12: </Border>

When you try to do this you get an exception like this one

>> Cannot animate the ‘Height’ property on a ‘System.Windows.Controls.Border’ using a ‘System.Windows.Media.Animation.DoubleAnimation’. For details see the inner exception.

and same for Width.

What I do in order to achieve the same behaviour without the need of setting a default width and height is to use a Scale Transform instead. Here is a snippet to get the same behaviour as the XAML above to animate the height

   1: <Border Background="Red" HorizontalAlignment="Center" VerticalAlignment="Center">

   2:    <TextBlock Text="CLICK ME" VerticalAlignment="Center" HorizontalAlignment="Center"/>

   3:    <Border.RenderTransform>

   4:        <ScaleTransform ScaleX="1" ScaleY="1" />

   5:    </Border.RenderTransform>

   6:    <Border.Triggers>

   7:        <EventTrigger RoutedEvent="UIElement.MouseDown">

   8:            <BeginStoryboard>

   9:                <Storyboard>

  10:                    <DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)" To="2"/>

  11:                </Storyboard>

  12:            </BeginStoryboard>

  13:        </EventTrigger>

  14:    </Border.Triggers>

  15: </Border>

Please note that there is a catch here. By using scale transform everything inside the actual control will be scaled. So if that is not what you want then you have a problem.

Yet of course there are solutions…. One of the solutions is to have an attached property to set the Height for you when the control is loaded. This can be achieved by setting the Height/Width to the ActualHeight/ActualWidth. Here is an attached property that I use in such cases.

   1: #region SetHeightToActual

   2:  

   3: /// <summary>

   4: /// SetHeightToActual Attached Dependency Property

   5: /// </summary>

   6: public static readonly DependencyProperty SetHeightToActualProperty =

   7:     DependencyProperty.RegisterAttached("SetHeightToActual", typeof(bool), typeof(WidthHeightBehaviour),

   8:         new FrameworkPropertyMetadata((bool)false,

   9:             new PropertyChangedCallback(OnSetHeightToActualChanged)));

  10:  

  11: /// <summary>

  12: /// Gets the SetHeightToActual property.  This dependency property 

  13: /// indicates ....

  14: /// </summary>

  15: public static bool GetSetHeightToActual(DependencyObject d)

  16: {

  17:     return (bool)d.GetValue(SetHeightToActualProperty);

  18: }

  19:  

  20: /// <summary>

  21: /// Sets the SetHeightToActual property.  This dependency property 

  22: /// indicates ....

  23: /// </summary>

  24: public static void SetSetHeightToActual(DependencyObject d, bool value)

  25: {

  26:     d.SetValue(SetHeightToActualProperty, value);

  27: }

  28:  

  29: /// <summary>

  30: /// Handles changes to the SetHeightToActual property.

  31: /// </summary>

  32: private static void OnSetHeightToActualChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

  33: {

  34:     if ((bool)e.NewValue)

  35:     {

  36:         var element = (FrameworkElement)d;

  37:         RoutedEventHandler handler = null;

  38:         handler = delegate

  39:         {

  40:             element.Height = element.ActualHeight;

  41:             element.Loaded -= handler;

  42:         };

  43:         element.Loaded += handler;

  44:     }

  45: }

  46:  

  47: #endregion

And here is the XAML where I am using the attached behaviour. It is nearly seamless

   1: <Border Background="Red" HorizontalAlignment="Center" VerticalAlignment="Center" local:WidthHeightBehaviour.SetHeightToActual="True">

   2:    <TextBlock Text="CLICK ME" VerticalAlignment="Center" HorizontalAlignment="Center"/>

   3:    <Border.Triggers>

   4:        <EventTrigger RoutedEvent="UIElement.MouseDown">

   5:            <BeginStoryboard>

   6:                <Storyboard>

   7:                    <DoubleAnimation Storyboard.TargetProperty="Height" To="300"/>

   8:                </Storyboard>

   9:            </BeginStoryboard>

  10:        </EventTrigger>

  11:    </Border.Triggers>

  12: </Border>

You can do the same thing for the Width or any other property of this kind (for example I use this technique also for Center property of ScatterViewItems in Surface development).

Hope this tip/trick helps :)

Happy coding

Service Locator in MVVM

While doing MVVM one of the common problems to solve is to have the ViewModel consume entities that are “replaceable”. Let me give you an example so that you can better understand what I mean by “replaceable“. Let’s say you have a ViewModel that is using a DataAccess entity to get some data from a data store. You want to be able replace the DataAccess entity so that you can mock this entity for unit testing. Besides this you want to also be able to have some sample data while at design time. And not to forget, when at runtime you want the data access to connects to the database or whatever data store you are using.

In order to do solve this problem I use the ServiceLocator pattern. The Service Locator pattern is very simple. You have a RegisterService method where you register the instance of the service you want to provide and a GetService method which you would use to get the service you want.

Here is the signature of both methods

   1: public T GetService<T>()

   2:  

   3: public bool RegisterService<T>(T service)

And here is how to use them in code

   1: //get the data access service

   2: var dataAccess = GetService<IPeopleDataAccess>();

   3:  

   4: //Register the data access service

   5: vm.ServiceLocator.RegisterService<IPeopleDataAccess>(new PeopleDataAccess());

So for example to test the the ViewModel I can write a unit test like this

   1: MainViewModel viewModel = new MainViewModel();

   2: viewModel.ServiceLocator.RegisterService<IPeopleDataAccess>(new PeopleDataAccessMock());

   3:  

   4: Assert.AreEqual(viewModel.People.Count, PeopleDataAccessMock.PeopleCount,

   5:    "Invalid number of People returned");

   6: Assert.AreEqual(viewModel.People[0].Name, PeopleDataAccessMock.FirstPersonName,

   7:    "Invalid item in people list");

   8: Assert.AreEqual(viewModel.People[0].Surname, PeopleDataAccessMock.FirstPersonSurname,

   9:    "Invalid item in people list");

So basically in this unit test I am just creating a mock object and testing that my ViewModel is exposing the data from the data access (which is mocked so the data returned by this data access is known in the test context)

This is all cool but now how can I use this in WPF and MVVM. So the first question that people ask is how do I create the ViewModel and set it as the DataContext. And also who is responsible of assigning the services that the ViewModel will consume. In order to do this I use AttachedBehaviour and the Factory design pattern.

I created a simple attached property that accepts a type of a Factory that is responsible for creating the ViewModel and register whatever services it needs. The attached property is very simple, here is the code for it

   1: public class ViewModelLoader

   2: {

   3:     #region FactoryType

   4:  

   5:     /// <summary>

   6:     /// FactoryType Attached Dependency Property

   7:     /// </summary>

   8:     public static readonly DependencyProperty FactoryTypeProperty =

   9:         DependencyProperty.RegisterAttached("FactoryType", typeof(Type), typeof(ViewModelLoader),

  10:             new FrameworkPropertyMetadata((Type)null,

  11:                 new PropertyChangedCallback(OnFactoryTypeChanged)));

  12:  

  13:     /// <summary>

  14:     /// Gets the FactoryType property.  This dependency property 

  15:     /// indicates ....

  16:     /// </summary>

  17:     public static Type GetFactoryType(DependencyObject d)

  18:     {

  19:         return (Type)d.GetValue(FactoryTypeProperty);

  20:     }

  21:  

  22:     /// <summary>

  23:     /// Sets the FactoryType property.  This dependency property 

  24:     /// indicates ....

  25:     /// </summary>

  26:     public static void SetFactoryType(DependencyObject d, Type value)

  27:     {

  28:         d.SetValue(FactoryTypeProperty, value);

  29:     }

  30:  

  31:     /// <summary>

  32:     /// Handles changes to the FactoryType property.

  33:     /// </summary>

  34:     private static void OnFactoryTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

  35:     {

  36:         FrameworkElement element = (FrameworkElement)d;

  37:         IFactory factory = Activator.CreateInstance( GetFactoryType(d) ) as IFactory;

  38:         if (factory == null)

  39:             throw new InvalidOperationException("You have to specify a type that inherits from IFactory");

  40:         element.DataContext = factory.CreateViewModel(d);

  41:     }

  42:  

  43:     #endregion

  44:  

  45: }

and you can use this in XAML like so

   1: <Window x:Class="ServiceLocatorSample.Main"

   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   4:     xmlns:vm="clr-namespace:MVVMHelper.Factory;assembly=MVVMHelper"

   5:     xmlns:fac="clr-namespace:ServiceLocatorSample.ViewModels.Factories"

   6:     Title="Main" Height="300" Width="300" vm:ViewModelLoader.FactoryType="{x:Type fac:MainViewModelFactory}">

Usually in the implementation of the factory I would check if the current state is at design time or runtime and accordingly register different services. Something like this

   1: public class MainViewModelFactory : IFactory

   2: {

   3:    public object CreateViewModel(DependencyObject sender)

   4:    {

   5:        var vm = new MainViewModel();

   6:        if (Designer.IsDesignMode)

   7:            vm.ServiceLocator.RegisterService<IPeopleDataAccess>(new DesignTimeData.DesignTimePeopleDataAccess());

   8:        else

   9:            vm.ServiceLocator.RegisterService<IPeopleDataAccess>(new PeopleDataAccess());

  10:        return vm;

  11:    }

  12: }

So with this factory at design time I would get Design time data showing in my designer but as soon as I run the app the actual data access (the real one that connects to the database) gets injected.

That’s it for today. Download the sample project and you will have a better idea of how all this works. Any questions or comments please let me know, I will be more than happy to answer :)

P.S In the sample I have the full MVVMHelper assembly that I use in my everyday work with MVVM so you will also have stuff like Mediator and other things that I will be blogging about very soon :)

Download the sample project

Playing with Shaders: Creating a water effect

Lately I’ve been looking at a really cool project on Codeplex for Pixel Shaders. The set of shaders in this library is awsome and really easy to use in you application….

All you need to do to consume any Shader is add a reference to the WPFShaderEffectLibrary class library and you can start using the shaders in XAML.What is really important is that you install the Shaders Build Task before trying to build the shader library (if you just add a reference to the ready build dlls you don’t even need to do this).

 

Water

So let’s have a look at how we can use shaders to simulate water on screen.

This is very easy all we need is a ripple shader effect. so something like this

   1: <Window.Resources>

   2:  

   3:    <Storyboard x:Key="waterAnimMain">

   4:        <DoubleAnimation Storyboard.TargetName="rippleMain" Storyboard.TargetProperty="Phase" To="0" From="10" Duration="0:0:2.0"  FillBehavior="Stop" />

   5:        <DoubleAnimation Storyboard.TargetName="rippleMain" Storyboard.TargetProperty="Amplitude" To="0" From="0.6" Duration="0:0:2.0"  FillBehavior="HoldEnd" />

   6:        <DoubleAnimation Storyboard.TargetName="rippleMain" Storyboard.TargetProperty="Frequency" To="0" From="30" Duration="0:0:2.5" FillBehavior="HoldEnd" />

   7:    </Storyboard>

   8:  

   9: </Window.Resources>

  10: <Grid Background="Transparent" >

  11:  

  12:    <Border>

  13:        <Border.Background>

  14:            <LinearGradientBrush EndPoint="0.93,0.925" StartPoint="0.094,0.125">

  15:                <GradientStop Color="#FF272788" Offset="0.112"/>

  16:                <GradientStop Color="#FF090916" Offset="0.721"/>

  17:                <GradientStop Color="#FE222267" Offset="0.28"/>

  18:                <GradientStop Color="#FE131339" Offset="0.453"/>

  19:                <GradientStop Color="#FF04040A" Offset="0.974"/>

  20:            </LinearGradientBrush>

  21:        </Border.Background>

  22:    

  23:    </Border>

  24:  

  25: </Grid>

  26:  

  27: <Window.Effect>

  28:    <shader:RippleEffect Amplitude="0" Frequency="0" Phase="0" x:Name="rippleMain"  />

  29: </Window.Effect>

This is our Shader

   1: <shader:RippleEffect Amplitude="0" Frequency="0" Phase="0" x:Name="rippleMain"  />

And we animate this shader like so to make the effect of water

   1: <Storyboard x:Key="waterAnimMain">

   2:      <DoubleAnimation Storyboard.TargetName="rippleMain" Storyboard.TargetProperty="Phase" To="0" From="10" Duration="0:0:2.0"  FillBehavior="Stop" />

   3:      <DoubleAnimation Storyboard.TargetName="rippleMain" Storyboard.TargetProperty="Amplitude" To="0" From="0.6" Duration="0:0:2.0"  FillBehavior="HoldEnd" />

   4:      <DoubleAnimation Storyboard.TargetName="rippleMain" Storyboard.TargetProperty="Frequency" To="0" From="30" Duration="0:0:2.5" FillBehavior="HoldEnd" />

   5:  </Storyboard>

We invoke this animation by having a DispatcherTimer trigger the animation every now and then and changing the Center property of the Shader to a random point from 0 to 1.

This already gets us very close but it still does not feel like real water. The trick is to animate to ripple effects at the same time. This will make the ripple effects expand together and thus making the control which has the shader applied look like water. Yet the problem is that you can only apply ONE shader per control. BUT you can have another shader on the parent control and that would still apply the shader on all children (I explain this in this article).

   1: <Window.Resources>

   2:  

   3:     <Storyboard x:Key="waterAnimMain">

   4:         <DoubleAnimation Storyboard.TargetName="rippleMain" Storyboard.TargetProperty="Phase" To="0" From="10" Duration="0:0:2.0"  FillBehavior="Stop" />

   5:         <DoubleAnimation Storyboard.TargetName="rippleMain" Storyboard.TargetProperty="Amplitude" To="0" From="0.6" Duration="0:0:2.0"  FillBehavior="HoldEnd" />

   6:         <DoubleAnimation Storyboard.TargetName="rippleMain" Storyboard.TargetProperty="Frequency" To="0" From="30" Duration="0:0:2.5" FillBehavior="HoldEnd" />

   7:     </Storyboard>

   8:  

   9:     <Storyboard x:Key="waterAnimSub">

  10:         <DoubleAnimation Storyboard.TargetName="rippleSub" Storyboard.TargetProperty="Phase" To="0" From="10" Duration="0:0:2.0"  FillBehavior="Stop" />

  11:         <DoubleAnimation Storyboard.TargetName="rippleSub" Storyboard.TargetProperty="Amplitude" To="0" From="0.6" Duration="0:0:2.0"  FillBehavior="HoldEnd" />

  12:         <DoubleAnimation Storyboard.TargetName="rippleSub" Storyboard.TargetProperty="Frequency" To="0" From="30" Duration="0:0:2.5" FillBehavior="HoldEnd" />

  13:     </Storyboard>

  14:  

  15: </Window.Resources>

  16: <Grid Background="Transparent" >

  17:  

  18:     <Border>

  19:         <Border.Background>

  20:             <LinearGradientBrush EndPoint="0.93,0.925" StartPoint="0.094,0.125">

  21:                 <GradientStop Color="#FF272788" Offset="0.112"/>

  22:                 <GradientStop Color="#FF090916" Offset="0.721"/>

  23:                 <GradientStop Color="#FE222267" Offset="0.28"/>

  24:                 <GradientStop Color="#FE131339" Offset="0.453"/>

  25:                 <GradientStop Color="#FF04040A" Offset="0.974"/>

  26:             </LinearGradientBrush>

  27:         </Border.Background>

  28:         <Border.Effect>

  29:             <shader:RippleEffect Amplitude="0" Frequency="0" Phase="0" x:Name="ripple" Center="{Binding ElementName=main, Path=(local:MouseBehaviour.LastMouseUp)}" />

  30:         </Border.Effect>

  31:     </Border>

  32:  

  33:     <Grid.Triggers>

  34:  

  35:         <EventTrigger RoutedEvent="UIElement.MouseUp">

  36:             <BeginStoryboard Storyboard="{StaticResource waterAnim}"/>

  37:             <BeginStoryboard Storyboard="{StaticResource waterAnimMain}"/>

  38:         </EventTrigger>

  39:     </Grid.Triggers>

  40:  

  41:     <Grid.Effect>

  42:         <shader:RippleEffect Amplitude="0" Frequency="0" Phase="0" x:Name="rippleSub"  />

  43:     </Grid.Effect>

  44:  

  45: </Grid>

  46:  

  47: <Window.Effect>

  48:     <shader:RippleEffect Amplitude="0" Frequency="0" Phase="0" x:Name="rippleMain"  />

  49: </Window.Effect>

And that’s it. Now we have a perfect water look thanks to the Codeplex Pixel Shader library :)

I created a sample app that shows all this. The app also has another feature so that you can touch the water by using the mouse and the water would ripple from the point you touch (of course this is with Behaviours so that you can even reuse it :D )

Happy coding :D

DOWNLOAD SOURCE CODE