Tuesday, December 28, 2010

Having a setter for an Observable Collection

Here's another cool way to override the getter for an observable collection without breaking your MVVM:


private ObservableCollection<string> _AvailableColumns = new ObservableCollection<string>();
        public ObservableCollection<string> AvailableColumns
        {
            get { return _AvailableColumns; }
            set
            {
                _AvailableColumns.Clear();
                foreach (var item in value)
                {
                    _AvailableColumns.Add(item);
                }
            }
        }

Now you can use it like :


new RequiredColumn() {RequiredColumnName="BSC",DefaultValue="",AvailableColumns=AvilableColumns};


and it will not break your notification changes :)

Sunday, December 19, 2010

Mediator for MVVMLight like the one by SachaBarber and Marlon

I am loving and using MVVMLight V3 for everything I can find. However there is one thing I feel missing in the Messenger. You can send messages of a particular type using GenericMessage<T> however you cannot send a particular message other than resorting to Magic Strings.

This is where the mediator implementation by sacha barber comes in : http://sachabarber.net/?p=477
I really like his implementation (which in turn was a simple modification of marlon's code).

I really liked that you can just signup for messages identified by a particular enum rather than a particular type (the MVVMLight way). 

However thanks to GenericMessage it was super easy to do. But first

What is a mediator
Since the view code behind should be unaware of the VM (view model). And VM should be unaware of other VMs. The only way to state something has happened is to use a Mediator (or a messenger).
More here : http://basaratali.blogspot.com/2010/12/all-you-want-to-know-to-mvvm-with.html

The Code 
All you need to modify below is add your own message enumerations:


public enum ViewModelMessages { SearchSitesStarted = 1 , SearchCellModified = 2 ,UploadSites=3,SelectUploadFile,UploadFileUpdated};
    public class GenericMessages
    {
        public ViewModelMessages MessageType { get; set; }
        public object Payload;   
    }
    public static class Mediator
    {
        public static void Send(ViewModelMessages messageType, object payload)
        {
            Messenger.Default.Send(new GenericMessages { MessageType = messageType, Payload = payload });
        }
        public static void Register(ViewModelMessages messageType, object recipient, Action<object> action)
        {
            Messenger.Default.Register(recipient, (genericMessage) =>
            {
                if (genericMessage.MessageType == messageType)
                {
                    action(genericMessage.Payload);
                }
            });
        }
    }



Sending Messages

Super easy to do:
Mediator.Send(ViewModelMessages.SearchSitesStarted, null);


Receiving Messages

Just as easy:
Mediator.Register(ViewModelMessages.SearchSitesStarted, this, (a) => { MessageBox.Show("Search Started"); });




All you want to know to MVVM with MVVMLight

This is my attempt at helping people finding gaps in their knowledge regarding MVVM. This does not explain the items presented in bold. The objective is that if you are unclear about what I mean you will google the terms in bold and be on your way. Happy reading!

WHY (or All you ever wanted to know about MVVM)? 
Here are the Four (yes 3+1 ... bear with me) key elements in a MVVM Application :
  1. XAML which contains the binding (Often losely called View)
  2. Code behind for your xaml file (Often losely called View)
  3. View Model
  4. Model
What XAML Knows
  • Now the objective is that XAML knows nothing about your VM other than the fact that it as its datacontext. (I prefer setting it using ViewModelLocator ... it comes for free with MVVM Light. If you use the Project templates that come with MVVMLight it will add it for you). 
  • It knows nothing of the code behind. If it does... you need to make a UserControl to abstract that away. 
  • Elements that have Command property raise commands. Elements that don't should use EventToCommand that comes with MVVMLight. These commands are RelayCommands by the way. 
  • Ofcourse important properties are bound to the viewmodel and use IValueConverters when required

What code behind knows
Almost nothing. 
  • If you feel that your code behind must contain some code then there is probably a component that you are using that is not MVVM Friendly (Contains normal .net properties that you cannot bind to and get change notifications). I suggest you wrap it up in a UserControl and abstract it away into a nice bindable component. 
  • Messages. Also called the Mediator, the Messenger is useful for some events that need to start some GUI function. E.g dialog box. A dialog box should never be placed in VM because that will prevent testing functionality of the VM without resorting to GUI Tests.
What ViewModel Knows
Nothing of the View or the View Code behind or other ViewModels. Its has these means of communication with other items:
  • Bindable properties. Generally the view model will inherit from INotifyPropertyChanged and implement properties that raise the PropertyChanged event. It is preferred that you use the ViewModelBase from MVVMLight.
  • RelayCommands. A part of MVVMLight. Your XAML View raises them using Command property or EventToCommand behaviour.
  • Messages. Again some actions require GUI interaction. The VM is resposible for initiating the message for it but the View code behind is responsible for showing the stuff :) 
What the Model Knows
Your domain object. Only interaction with ViewModel. 
  • You should extend ViewModelBase (or implement INotifyPropertyChanged) for this. This will help you store instances of your model as an ObservableCollection in your ViewModel. 
  • Either there will be some ViewModel that will
    • inherit from your model or 
    • contain it as an ObservableCollection or 
    • Contain an instance as a Bindable Property. 

Finally
Now that wasn't so hard was it. Also if you know all there is to know about Binding, StaticResource, ItemTemplate you should be all set :) 

Enjoy!

Saturday, December 18, 2010

An MVVM Version of Bing Maps with Google / Yahoo / Open Street Maps integrated

I was working with Bing Maps when I found that ZoomLevel and BoundingRect were not Dependency Properties. However you can easily make them since it exposed the ViewChangeEnd event.

Also I wanted to wrap up various types of maps in a simple to use control. I got the tile sources from here
http://pietschsoft.com/post/2010/06/14/Display_Google_Maps_Imagery_using_Bing_Maps_Silverlight_Control.aspx
I just had to update the Satellite view to the latest version since the khm source no longer works.

I made a UserControl out of it. Shared it here : (SourceCodehttp://code.google.com/p/mvvmslmaps/downloads/list
In Action:

Lessons Learned
Just one: I add a MapItemsLayer to the maps in my application so I wanted to redirect the Content Property of the custom UserControl to the Content Property of my bing maps instance.

It was super easy to do :

  • Added the attribute : [ContentProperty("Children")] to your Control. 
  • Added the following as a property : 
             public UIElementCollection Children
            {
                get { return MyMap.Children; }
            }

    This means that when I add a MapItemsControl :

    <Control:MVVMMapControl x:Name="MyMap"> 
                <m:MapItemsControl x:Name="ListOfItems" ItemsSource="{Binding Sites}" ItemTemplate="{StaticResource CellTemplate}" ></m:MapItemsControl> 
            </Control:MVVMMapControl>


    It gets added as a child of my bing maps instance.

    Tuesday, December 14, 2010

    ValueTypes cannot be modified by extension methods

    I was converting a WPF code to silverlight when I noticced that Silverlight does not have the Offset Member method to the point structure. I thought I could get away with a dead simple extension method :

    namespace ConsoleApp 
    { 
    
        public static class SlUtils
        { 
            public static void OffsetSL(this System.Windows.Point p, double CenterX, double CenterY)
            { 
                p.X += CenterX; 
                p.Y += CenterY; 
                // p = new System.Windows.Point(p.X, p.Y); does not help either
            } 
        } 
    
        class Program 
        { 
            static void Main(string[] args) 
            { 
                System.Windows.Point p = new System.Windows.Point(0, 0);
                p.OffsetSL(10, 20);
                Console.WriteLine("{0},{1}", p.X, p.Y); // prints {0,0} // FAIL 
                p.Offset(10, 20);
                Console.WriteLine("{0},{1}", p.X, p.Y); // prints {10,20} 
                Console.ReadKey(); 
            } 
        } 
    } 
    
    I was so wrong :) The extension method cannot modify a value type. What you can do is return from an extension method (instead of void) the value you want... ah well you can't have Everything.

    Enjoy!

    Monday, December 6, 2010

    Exam 70-502 Passed

    The exam was great. Really I am not saying that because of my score. I am saying that because it was much more fun (for me at least) than 70-536. WPF (and now Silverlight) is a technology I am deeply passionate about. Maybe its because of my love for beauty and elegance. Maybe its because I hate to say to someone that adding a really classy button just the way you want it to your application will take me three days.

    PS: I sincerely believe that 70-536 made me a better programmer. You will not catch me asking around about StreamReader or how to determine drives in c#.  Although a quick google search would help you ... but I will not need one ... I hope :) Oh not to mention : http://msdn.microsoft.com/en-us/library/system.io.path.getfilenamewithoutextension.aspx or http://msdn.microsoft.com/en-us/library/wz42302f.aspx (these weren't asked of me ... but I remembered them).

    Now how did I prepare for this exam. 
    Well I have had an eye on WPF for three years. Recommended it to a colleague two years ago (I myself was experimenting with python + flex)  and did a project in WPF about a year and a half ago. Simultaneously I had read the book WPF unleashed (http://www.amazon.com/Windows-Presentation-Foundation-Unleashed-WPF/dp/0672328917).This book is basically what got me really motivated to start doing Microsoft certifications in the first place (I devoted myself to a technology I loved). The official book would not be sufficient without this. Everyone will tell you that. Without this I wouldn't know what {Binding} meant (bind directly to datacontext) or that a style without an explicit key but a targettype gets an implicitly set key.

    It wasn't until mid of this year that I finally got the time to start doing it. First I applied for exam 70-536. Just then the new certifications came out (VS2010). But I really wanted the title WPF technology specialist, so I decided to go with the old certifications anyways. Additionally I don't feel comfortable about doing a certification without an official "book" (VS2010 book isn't out yet). For this I read the book cover to cover one and a half times (second time just the highlights to memorize what I thought deserved memorizing the first time I read it). This is the "book" http://www.amazon.com/MCTS-Self-Paced-Training-Exam-70-502/dp/0735625662/ref=sr_1_5?ie=UTF8&s=books&qid=1291632845&sr=1-5 I loved this book. Without this book I wouldn't have known that there are EnterActions for property triggers.

    I still had time (about a month due to prometric test center being booked in my city) ... I decided to read WPF Unleashed 4 http://www.amazon.com/WPF-4-Unleashed-Adam-Nathan/dp/0672331195 I intend to finish it someday but just got curious about silverlight as it is now. And then I picked up Silverlight 4 Unleashedhttp://www.amazon.com/Silverlight-4-Unleashed-Laurent-Bugnion/dp/0672333368 Now note that I am reading this book after preparing 70-502. This meant I know the value of learning ... really learning every single API that is exposed. And I couldn't put this book down. I simply love it. It showed me how to make my own controls in the very first chapter. I can see XAML now (just like I could see c#). Make my applications Blendable. And I really feel comfortable with MVVM (and yes I have made applications without MVVM ... I am not proud ... and I don't intend to do that ever again). This alone made it the best book on WPF (yes WPF... even though it does not claim it) ever!

    And that's it ... the exam was today morning at 10:30 am ... and the rest is history. Thanks for everyone who waited patiently while I prepared for this exam. Love you mom for tolerating my eternal business and keeping me well fed and energized.