Click here to Skip to main content
Click here to Skip to main content

Silverlight File Manager

By , 1 Aug 2010
 

Introduction

This project demonstrates an implementation of the View Model Style pattern to create a simple Silverlight File Manager. This pattern allows a programmer to create an application that has absolutely no UI. The programmer only creates a ViewModel and a Model. A designer with no programming ability at all, is then able to start with a blank page and completely create the View (UI) in Microsoft Expression Blend 4 (or higher).

The Power of the View Model Style

This Silverlight project is not a full featured file manager, but, it actually works and hopefully demonstrates a non-trivial example of a View Model Style Silverlight project.

The point however, is about the View Model Style pattern. We will highlight these important points:

  • The Programmer creates code that consist of collections, properties, and Commands (that implement ICommand).
  • The Designer uses Expression Blend, and creates the complete UI, without writing any code.

The Starter Solution

We will start with the solution contained in the MVMFileManager_BaseStartProject.zip file. This consists of a starter Silverlight project, and a standard ASP.NET website that shows files and folders that are contained in the Files folder. Note, this website could be implemented in another language such as PHP and the Silverlight application would still work.

Two simple classes, SilverlightFolder and SilverlightFile, are used to hold the collection of files and folders that the web service in the ASP.NET website will return.

namespace MVMFileManagerSite
{
    [Serializable]
    public class SilverlightFolder
    {
        private ObservableCollection<silverlightfolder /> _SubFolders;

        public ObservableCollection<silverlightfolder /> SubFolders
        {
            get
            {
                if (_SubFolders == null)
                {
                    _SubFolders = new ObservableCollection<silverlightfolder />();
                }
                return _SubFolders;
            }
            set
            {
                _SubFolders = value;
            }
        }

        public string FolderName { get; set; }
        public string FullPath { get; set; }

    }

    [Serializable]
    public class SilverlightFile
    {
        public string FileName { get; set; }
        public string FilePath { get; set; }
    }
}

If we right-click on the Webservice.asmx file, and select View in Browser, we can see the web methods.

The GetLocalFolders method returns a collection of folders in the Files directory.

The GetLocalFiles method requires a folder name to be passed as a parameter, and it returns a collection of file names, as well as a link to download the file (by passing the folder and file name to the DownloadFile.aspx file).

The Programmer - The Model and the View Model

We will now open the solution in Expression Blend 4 (or higher) and create the Model and the ViewModel. However, first, we will add a simple class to support Commanding. Commanding will allow the Designer to raise an event in the ViewModel.

We will use code created by John Papa that he posted in his blog "5 Simple Steps to Commanding in Silverlight".

Right-click on the Classes folder in the MVMFileManager Silverlight project (that is part of the MVMFileManager starter solution), and select Add New Item…

Add a class called DelegateCommand.cs and click OK.

Replace all the code with the following code:

using System.Windows.Input;
using System;

// From http://johnpapa.net/silverlight/5-simple-steps-to-commanding-in-silverlight/
public class DelegateCommand : ICommand
{
    Func< object, bool > canExecute;
    Action< object > executeAction;
    bool canExecuteCache;

    public DelegateCommand(Action< object > executeAction, Func< object, bool > canExecute)
    {
        this.executeAction = executeAction;
        this.canExecute = canExecute;
    }

    #region ICommand Members

    public bool CanExecute(object parameter)
    {
        bool temp = canExecute(parameter);

        if (canExecuteCache != temp)
        {
            canExecuteCache = temp;
            if (CanExecuteChanged != null)
            {
                CanExecuteChanged(this, new EventArgs());
            }
        }

        return canExecuteCache;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        executeAction(parameter);
    }

    #endregion
}

In the Models folder, add a class called SilverlightFolders.cs and replace the code with the following code:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ServiceModel;
using MVMFileManager.FileManager;
using MVMFileManager;

namespace MVVMFileManager
{
    public class SilverlightFolderAndFiles
    {
        MainViewModel _MainViewModel;

        #region GetWebserviceAddress
        private string GetWebserviceAddress()
        {
            string strXapFile = @"/ClientBin/MVMFileManager.xap";

            string strBaseWebAddress =
                App.Current.Host.Source.AbsoluteUri.Replace(strXapFile, "");

            return string.Format(@"{0}/{1}", strBaseWebAddress, @"WebService/WebService.asmx");
        }
        #endregion

        #region GetFolders
        public void GetFolders(MainViewModel objMainViewModel)
        {
            // Set MainViewModel
            _MainViewModel = objMainViewModel;

            // Set up web service call
            WebServiceSoapClient objWebServiceSoapClient =
                new WebServiceSoapClient();

            EndpointAddress MyEndpointAddress = new
                EndpointAddress(GetWebserviceAddress());

            objWebServiceSoapClient.Endpoint.Address = MyEndpointAddress;

            // Call web method
            objWebServiceSoapClient.GetLocalFoldersCompleted +=
                new EventHandler< GetLocalFoldersCompletedEventArgs >(objWebServiceSoapClient_GetLocalFoldersCompleted);
            objWebServiceSoapClient.GetLocalFoldersAsync();

        }

        void objWebServiceSoapClient_GetLocalFoldersCompleted(object sender, GetLocalFoldersCompletedEventArgs e)
        {
            foreach (var item in e.Result)
            {
                _MainViewModel.SilverlightFolders.Add(item);
            }

            // Get the files for the first Folder
            if (e.Result != null)
            {
                GetFiles(_MainViewModel, e.Result[0]);
            }
        } 
        #endregion

        #region GetFiles
        public void GetFiles(MainViewModel objMainViewModel, SilverlightFolder objSilverlightFolder)
        {
            // Set MainViewModel
            _MainViewModel = objMainViewModel;

            // Set up web service call
            WebServiceSoapClient objWebServiceSoapClient =
                new WebServiceSoapClient();

            EndpointAddress MyEndpointAddress = new
                EndpointAddress(GetWebserviceAddress());

            objWebServiceSoapClient.Endpoint.Address = MyEndpointAddress;

            // Call web method
            objWebServiceSoapClient.GetLocalFilesCompleted += 
                new EventHandler<GetLocalFilesCompletedEventArgs>(<getlocalfilescompletedeventargs />objWebServiceSoapClient_GetLocalFilesCompleted);
            objWebServiceSoapClient.GetLocalFilesAsync(objSilverlightFolder.FolderName);

        }

        void objWebServiceSoapClient_GetLocalFilesCompleted(object sender, GetLocalFilesCompletedEventArgs e)
        {
            foreach (var item in e.Result)
            {
                _MainViewModel.SilverlightFiles.Add(item);
            }
        }
        #endregion
    }
}

This is a class that calls the GetFolders and GetFiles web service methods. A few things to note:

  • The methods accept an instance of the ViewModel (that will be created in the next step) as one of their parameters.
  • The instance of the ViewModel is stored in the _MainViewModel private variable to be later used by the web service call back method.
  • When the asynchronous method returns, it hydrates the appropriate collection on the ViewModel.

In the ViewModels folder, add a class called MainViewModel.cs and replace the code with the following code:

using System;
using System.ComponentModel;
using System.Windows.Input;
using System.Collections.ObjectModel;
using MVMFileManager.FileManager;

namespace MVVMFileManager
{
    public class MainViewModel : INotifyPropertyChanged
    {
        public MainViewModel()
        {
            // Set the command property
            SetFilesCommand = new DelegateCommand(SetFiles, CanSetFiles);

            // Set default values
            SilverlightFolders = new ObservableCollection< SilverlightFolder >();
            SilverlightFiles = new ObservableCollection< SilverlightFile >();
            
            // Pass a reference of this class to the method to get the Folders
            SilverlightFolderAndFiles objSilverlightFolderAndFiles = new SilverlightFolderAndFiles();
            objSilverlightFolderAndFiles.GetFolders(this);
        }

        #region Commanding
        public ICommand SetFilesCommand { get; set; }

        public void SetFiles(object param)
        {
            // Get the Folder selected
            SilverlightFolder objSilverlightFolder = (SilverlightFolder)param;

            // Clear the file list
            SilverlightFiles = new ObservableCollection< SilverlightFile >();

            // Pass a reference of this class to the method to get the Files
            SilverlightFolderAndFiles objSilverlightFolderAndFiles = new SilverlightFolderAndFiles();
            objSilverlightFolderAndFiles.GetFiles(this, objSilverlightFolder);
        }

        private bool CanSetFiles(object param)
        {
            return true;
        } 
        #endregion

        #region Folders
        private ObservableCollection< SilverlightFolder > _SilverlightFolders;
        public ObservableCollection< SilverlightFolder > SilverlightFolders
        {
            get { return _SilverlightFolders; }
            private set
            {
                if (SilverlightFolders == value)
                {
                    return;
                }

                _SilverlightFolders = value;
                this.NotifyPropertyChanged("SilverlightFolders");
            }
        } 
        #endregion

        #region Files
        private ObservableCollection< SilverlightFile > _SilverlightFiles;
        public ObservableCollection< SilverlightFile > SilverlightFiles
        {
            get { return _SilverlightFiles; }
            private set
            {
                if (SilverlightFiles == value)
                {
                    return;
                }

                _SilverlightFiles = value;
                this.NotifyPropertyChanged("SilverlightFiles");
            }
        }
        #endregion
    
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }
}

This is the class that will be consumed by the designer. The designerwill not actually need to see this code, it will show up in Blend, in the Data section, when the designer sets this class as the DataContext for the UI page.

Note, that this class implements ObservableCollection, so that changes to values stored in the class, will cause a notification to any UI element that is bound to it, so it can automatically update. The class also implements INotifyPropertyChanged so that properties will also provide automatic change notification to any UI elements that are bound to them.

The SetFilesCommand property implements an ICommand. A UI element such as a Button, or in this example, a selected node on a TreeView, can bind to this property and call the SetFiles method (that was registered using the DelegateCommand in the class constructor).

The Designer - The View

THE PROGRAMMER HAS LEFT THE BUILDING!

We have finally arrived at the real point of this article. Allow me a moment to drive home the point that the View Model Style pattern in Silverlight allows us to create an application, yet not specify a UI at all. The UI can be created entirely in Blend without writing a single line of code.

Why is that important? Because the programmers need no longer hold the designers back. The programmers don't intend to hold anyone back (after all I am a programmer), but normally nothing can go to production without the programmers implementing it.

Designers can now take charge of a project that has implemented the View Model Style pattern, and create new innovative user interfaces that do not have to go through a programmer. We can expect a lot of advances in user interfaces in the coming years, now that we have taken the "shackles" off of the designers.

Now, imagine that a programmer has created the previous files. This project can now be turned over to a designer to actually create the UI. Just in case you missed it, let me say this again, The programmer has left the building! and as the designer, you can deliver this project to production without writing another line of code.

Just to make sure you're ready to go, from the toolbar, select Project, then Build Project. The project should build without errors.

Double-click on the MainPage.xaml file in the Projects window to open it.

This will open the file. It is currently a blank UI.

Click on LayoutRoot in the Objects and Timeline window. Next, in the Properties window, click the New button next to DataContext.

Select MainViewModel and click OK. The DataContext is now set. All child objects of the LayoutRoot will have access to the data and commands provided by the DataContext.

If you click on the Data tab...

... and expand MainViewModel (under the Data Context section). You will see the collections and commands exposed by the MainViewModel class. The designer is able to interact with the ViewModel by simply dragging items from this window onto controls on the design surface.

The File Manager UI

Click on the Assets icon on the Tools bar.

Type "Grid" in the Search box. Click on the Grid and drag it to the design surface.

Position the Grid on the design surface and expand it's size so that it fills most of the page. Hover the mouse over the center of the Grid (on the blue bar), a positioning line will appear.

Click the mouse to create a split in the Grid creating two cells.

Click the Assets button and search for the ScrollViewer and drag it to one of the cells in the Grid.

Perform the action again, and drag a ScrollViewer into the other cell of the Grid.

In the properties of each ScrollViewer, click the Advanced Options box...

And Reset the values.

This will cause each ScrollViewer to completely fill it's cell in the Grid.

Click on each of the ScrollViewers in the Objects and Timeline window and rename them to Folders and Files respectively.

Search for the TreeView control

Drag and drop it into the Folders ScrollViewer in the Objects and Timeline window.

In the Properties for the TreeView, set the Width and Height to Auto by clicking the Set to Auto button for each setting.

Click on LayoutRoot in the Objects and Timeline window to select it.

In the Data tab, click and drag the SilverlightFolders collection to the Objects and Timeline window.

Drop the collection on the TreeView.

In the Projects window, right-click on the MVMFileManagerSite project and set it as the Startup Project

Also, right-click on the Default.aspx page and set it as the Startup

Hit the F5 key to run the project. You may see a warning message, just click Yes

The project will run and the folders will show, however, they are not formatted correctly.

Note, you will see an error in the Errors window. The reason for this is that the Blend designer is trying to show sample data in the designer but it cannot run the web service that supplies the data. However, as you can see it does work at run-time. You can use the command (in your code) DesignerProperties.IsInDesignTool to determine if the code is being called from Blend and provide sample data that the designer can display. I did not implement that in this example because I wanted to focus on the View Model Style code.

In Blend, in the Objects and Timeline window, right-click on the TreeView control and select Edit Additional Templates > Edit Generated Items (Item Template) > Edit Current.

This will take you to the Template editing mode. Select the lower TextBlock (that the file Path is bound to) and right-click on it and select Delete, to delete it.

In the Projects window, open the Images folder in the MVMFileManager project and click on the Folder.png file.

Drag and drop it anywhere on the design surface.

It will also appear in the Objects and Timeline window, click on it and drag it so that it is on top of the TextBlock.

Click on the StackPanel in the Objects and Timeline window, and in the Properties window, set it's Orientation to Horizontal.

Click on the TextBlock in the Objects and Timeline window, and in the Properties window, set it's left Margin to 5.

Click the Return Scope icon, in the Objects and Timeline window, to return to normal design mode.

Hit the F5 key on your keyboard to run the project. The folders are looking much better. Now on to the files.

Click on LayoutRoot in the Objects and Timeline window to select it.

In the Data tab, click and drag the SilverlightFiles collection to the design surface.

In the Objects and Timeline window, it will appear below the Files ScrollViewer, it needs to be inside the ScrollViewer.

In the Objects and Timeline window, drag it so that it is inside the Files ScrollViewer.

In the Properties for the ListBox, set the Width and Height to Auto by clicking the Set to Auto button for each setting.

Hit the F5 key on your keyboard to run the project. The files show, but they are not formatted correctly. We should see the file name, and when we click on it, we want to download the file. We can do this by using a HyperlinkButton control.

In Blend, in the Objects and Timeline window, right-click on the ListBox control and select Edit Additional Templates > Edit Generated Items (Item Template) > Edit Current.

This will take you to the Template editing mode. Select the both TextBlocks and right-click on them and select Delete, to delete them.

In the Assets, search for the HyperlinkButton.

Drag and drop it on the design surface.

In the Properties for the HyperlinkButton, click on the Advanced options box for the Content property.

Select Data Binding...

  • Select the Data Context tab
  • Select FileName (under SilverlightFiles)
  • Click OK

In the Properties for the HyperlinkButton, click on the Advanced options box for the NavigateUri property.

Select Data Binding...

  • Select the Data Context tab
  • Select FilePath (under SilverlightFiles)
  • Click OK

Hit the F5 key on your keyboard to run the project. The files for the first folder will display, and when you click on a file it will download. However, if you change folders the files will not change.

Now, how to show the files for the selected folder?

In Blend, Click the Return Scope icon, in the Objects and Timeline window, to return to normal design mode.

Click on the Assets button on the Tools window.

Type “InvokeCommand” in the search box and the InvokeCommandAction behavior will show. (if you don’t see this, install the Silverlight 4 SDK). Drag and drop it on the TreeView control (either in the Objects and Timeline window or on the design canvas).

The Behavior will show under the TreeView control in the Objects and Timeline window.

Click on the Behavior in the Objects and Timeline window, and in the Properties window, set the EventName to SelectedItemChanged (so that the Behavior will fire when the selected item is changed in the TreeView).

Click the Data bind icon next to Command (under Common Properties).

  • Select the Data Context tab
  • Select SetFilesCommand (under MainViewModel)
  • Click OK

This instructs the Behavior to call the SetFilesCommand in the ViewModel.

Click the Advanced options box next to CommandParameter (under Common Properties).

Select Data Binding…

  • Select the Element Property tab
  • Select [TreeView] (in the Scene elements window)
  • Select SelectedItem (in the Properties window)
  • Click OK

This instructs the Behavior to pass the SilverlightFolder object, that the currently selected TreeView item is bound to, to the SetFilesCommand in the ViewModel.

Hit the F5 key on your keyboard to compile and run the project. The TreeView control will show the Folder structure, and when you click on a Folder it will show the files for the selected folder.

Is there more to the View Model Style ?

Yes there is, you will find the need to use Value Converters and different Behaviors as well as the Visual State Manager in order to have the full set of tools you need to complete any Silverlight project. To learn how to use these tools, all you have to do is go to:

http://www.microsoft.com/design/toolbox/

This site will give to the free training you need to master Expression Blend. It also will cover design principals to make you a better designer. Really, it cannot get any easier. The time to join the "revolution" is now.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

About the Author

defwebserver
Software Developer (Senior) http://ADefWebserver.com
United States United States
Michael Washington is a Microsoft Silverlight MVP. He is a Silverlight developer and an ASP.NET, C#, and Visual Basic programmer.
 
He is a DotNetNuke Core member and has been involved with DotNetNuke for over 4 years. He is the Co-Author of Building Websites with DotNetNuke (4 and 5).
 
He is one of the founding members of The Open Light Group (http://openlightgroup.net).
 
He is the founder of http://LightSwitchHelpWebsite.com
 
He has a son, Zachary and resides in Los Angeles with his wife Valerie.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberSavalia Manoj M23-Jan-13 21:56 
Good Work...!!
GeneralMy vote of 5memberFarhan Ghumra17-Aug-12 0:02 
Excellent
QuestionAdd IsBusy to MainViewModel?membercthue27-Apr-12 6:51 
This was a great intro to MVVM. I would like to add a busy indicator, but cannot determine how to implement it. Confused | :confused:
Questionhelp with base start projectmemberpeter andrevs1-Sep-11 9:05 
hi i found your article series on this topic incredibly interesting and now im trying to make something similar from the bottom up.

how ever try as i might i cant make my own base start from

could you please help me with that by making a small explanation on how to make that base start from the bottom up as im having a lot of trouble with that

i know im asking a lot here since its been a long time since you wrote this article but i think that understanding how to make that would really help my education as a programer
GeneralMy vote of 5memberHabib201021-Jul-11 5:45 
nice
Generalhave 5memberPranay Rana30-Dec-10 21:26 
Excellent
For any question : http://pranayamr.blogspot.com/
 
vote my article :

Learn SQL to LINQ ( Visual Representation )


Calling WCF Services using jQuery

GeneralRe: have 5memberdefwebserver31-Dec-10 3:32 
Thank You!
GeneralNameserver typo [modified]memberDHCut18-Aug-10 4:22 
Hi Michael
Thanks for a really easy-to-follow article.
I do like to get a non-trivial intro.
When I built it, I got compilation errors:-
There is a typo in the cutNpaste code. I mention this to try to save others time.
The Namespace in
SilverlightFolders.cs
AND
MainViewModel.cs
is there as :-
namespace View Model StyleFileManager
But it needs to be:-
namespace MVVMFileManager
 
If you don't get the namespaces set to MVVMFileManager, then the project only partially works - even if it builds ok.
It works now. Wink | ;)
 
Now I'm going to try to step thru it.
Regards
David

modified on Wednesday, August 18, 2010 11:16 AM

GeneralRe: Nameserver typomemberdefwebserver18-Aug-10 5:46 
Thank you, I fixed the article. Right now the best tutorial is:
 
RIATasks: A Simple Silverlight CRUD Example (using View Model)[^]
GeneralExcellent StuffmentorKunalChowdhury2-Aug-10 7:22 
Hi Michael,
 
No need to tell anything special. Your articles are always great and you proved it again here. Have my 5. Thumbs Up | :thumbsup:

 
Don't forget to Click on [Vote] and [Good Answer] on the posts that helped you.


Regards - Kunal Chowdhury | Software Developer | Chennai | India | My Blog | My Tweets | Silverlight Tutorial

GeneralRe: Excellent Stuffmemberdefwebserver2-Aug-10 7:58 
Thanks! I appreciate it. Every vote counts.
GeneralSorry, just didn't get itmemberMr Yossu29-Jul-10 12:33 
Don't mean to sound critical, but I just didn't get much from this article. I appreciate the amount of time you must have put into it, but as a newbie to MVVM, I'm no clearer on it than I was before I read the article.
 
After a (very) brief overview of MVVM, you launched into the code with several "copy all of this code" blocks. This is the point where some explanation would have been helpful. Obviously the two classes you created for the files and folders don't need explanation, but the others did. What exactly were they all doing?
 
Also, you spent a lot of time walking through the UI creation in Blend, without any explanation as to what you were doing. I followed along, but really didn't understand why I was clicking and what I was doing.
 
To top it all off, the final step failed. I followed your instructions exactly about adding the InvokeCommandAction behavior, but when I tried to run the project, I got three compile errors...
 
1) the property triggers does not exists on the type treeview
2) the tag eventtrigger does not exist in xml namespace...
3) the tag invokeactioncommand does not exist in xml namespace...
 
Very disappointed. I was hoping to learn what MVVM was, and how it would help me.I'm no further on than before I read the article.
 
Again, please don't take this as a criticism. I appreciate the amount of work you must have put in to write this article, but I don't think you achieved your objective.
GeneralRe: Sorry, just didn't get itmemberdefwebserver29-Jul-10 13:15 
First, Thank you for taking time to leave feedback. This must have taked you time and you are very clear about your concerns.
 
Can we take this one step at a time:
 
1) If you download the sample code, does it work for you? If so, can you think of anything that I have ommited that I ned to fix in the tutorial? If the code attached to te article, doesn't work, then I have to figure out why.
 
2) The other issues, I think are related to expectations. However, they are resonable, and I understand, and I think that because this is one of my earlier tutorials I was unable to explain well. I feel that I have done a better job with these:
 
Silverlight View Model Style: An (Overly) Simplified Explanation
http://openlightgroup.net/Blog/tabid/58/EntryId/89/Silverlight-MVVM-An-Overly-Simplified-Explanation.aspx[^]
 
RIATasks: A Simple Silverlight CRUD Example
RIATasks: A Simple Silverlight CRUD Example (using View Model)[^]
 
Silverlight RIA Tasks 2: Dynamic View Models
Silverlight RIA Tasks 2: Dynamic View Models[^]
 
Using The Silverlight DataGrid with View Model
Using The Silverlight DataGrid with View Model / MVVM[^]
GeneralRe: Sorry, just didn't get itmemberMr Yossu30-Jul-10 0:18 
Hello,
 
Thanks for your reply. To answer your questions...
 
1) I downloaded the base start project, and followed your steps. Everything worked fine until I tried to run it after adding the InvokeCommandAction behavior. That's when I got the errors. I downloaded the final project, and that worked fine, so it's obviously something I've done wrong whilst implementing the InvokeCommandAction behavior, but having tried it a few times, and read your article over and again, I can't see what it is.
 
2) You're right, it's mostly expectations. I got the impression from the intro of your article that you were going to explain how to implement the View Model Style pattern in a Silverlight application. I was hoping that you were going to explain the steps necessary to implement the pattern, not just provide code to cut and paste. Maybe I misunderstood your intentions, but I was hoping to see something like "To get the View to signal changes to the ViewModel, we need to do abc, and here's the code to do it..." and then explain exactly what the code was doing. Instead, you just presented code without any explanation.
 
Again, this isn't a criticism, it may just be that this article wasn't aimed at me.
 
As for your other articles, I had already read the simple explanation of MVVM, and thought it was very good. It gave a brief, high-level overview, and left me interested in seeing how to implement the pattern in practice. That's why I came to this article, thinking it was the next step from that.
 
I had also seen the first RIATasks article, but hadn't followed it through. I started with this one as it looked a little simpler. It looks to have a very similar structure to this one though, in that you present a load of code without an explanation of what it's there for.
 
I hadn't seen the 3rd or 4th, but a brief look gives the same impression.
 
I do appreciate the amount of work you've put in here, and intend to go through the other articles carefully, but if you don't mind, I would like to suggest a way you could improve all of these (and any future) articles immensely.
 
From the beginning of your article, we have an idea of the point of MVVM, and realise that to implement it, we need to have the UI behaviour in the VM, instead of in a combined UI layer as most of us have done before. So the obvious problem that arises is how to do this. At this stage, a high-level explanation of the principle of how the VM interacts with the View (and with the Model for that matter) would give a conceptual understanding. You can then introduce (using pseudo-code, or a cut-down code that only shows the main points) a simplified methodology for implementing that interaction. Then when you present the full code, the reader should be able to pull out the important points, and concentrate on those, whilst leaving the extra bits (that aren't the centre of the issue, but are needed for extra reason) for later.
 
I don't know if I've made myself clear enough here, but hopefully you can see what I mean. Sometimes your code has to have helper methods to allow the full system to work, but these helper methods aren't part of the main infrastructure. If you give a simplified methodology, then you concentrate on the main methods, and allow the reader to see how the core implementation works. That helps clarify the point you're making.
 
Anyway, this reply is getting too long, so I'll stop here. Thanks again for the articles, and the reply. I hope my comments have been useful. I will read your other articles and see how I get on with those.
GeneralRe: Sorry, just didn't get itmemberdefwebserver30-Jul-10 2:28 
Thank you for your feedback, it gives me valuable information for future articles.
 
I have actually stopped writing MVVM articles and instead write about "View Model". Mostly the reason is that there is too much controversy on exactly how to implement "the pattern". Also, most people want to do things their own way anyway. Few people ever read articles like this and they go out and create applications EXACTLY like the article describes.
 
So now I just show people a technique, hopefully explain what it is that I am showing you, and then I step aside. What YOU will come up with will be BETTER than what I have showed you!
 
So I only want to show you how you can use Binding. For now it is using Behaviors. That's it. You may notice, that in my articles, I use different techniques for the Model, sometimes using Rx Extensions, sometimes not.
 
But, the best article to begin with is the RIA Tasks[^]. In that one I feel I do explain ever step. There is very little "overview of the pattern", but that is intentional.
GeneralRe: Sorry, just didn't get itmemberMr Yossu1-Aug-10 1:07 
Thanks for the reply. I'm off to read the RIATasks articles then. If I have nay comments, I'll post them there.
 
Thanks again
GeneralExcellent - & why I'm a Silverlight Designer!!!memberAlan Beasley9-Apr-10 7:19 
Brilliant, & a very comprehensive illustrated tutorial.
I know how long it takes to put together a tutorial with that much detail & illustrations.
 
So thanks Michael! 5 stars!!! Big Grin | :-D
 
P.S. I can leave all that nasty horrible code to someone else, & make stuff pretty! Laugh | :laugh:
 
Alan
GeneralRe: Excellent - & why I'm a Silverlight Designer!!!memberdefwebserver9-Apr-10 7:33 
Thanks for the feedback Alan,
 
I hope you can see that the PROBLEM with this article is that the final UI sucks! Meaning, I tell you that a Designer can make a great UI, but since I don't have one, the article ends and there is no GREAT UI.
 
I know we plan to make a better example in the future, however, If you were to open up the completed project and erase my UI and do another one I would update my article Smile | :) Smile | :) Smile | :)
GeneralRe: Excellent - & why I'm a Silverlight Designer!!!memberAlan Beasley9-Apr-10 7:53 
defwebserver wrote:
I hope you can see that the PROBLEM with this article is that the final UI sucks

 
That's a bit harsh!
The diplomat in me thinks: We have a starting point....
 
(Sorry, not much of a diplomat! Big Grin | :-D )
 
defwebserver wrote:
I know we plan to make a better example in the future, however, If you were to open up the completed project and erase my UI and do another one I would update my article

 
Sounds like a plan, as I don't think Sacha would mind me choosing a ListBox or TreeView, as my next Control to Style.
And it may as well be for your application, as anything else I was thinking of.
 
I start looking into it...
 
Alan
GeneralRe: Excellent - & why I'm a Silverlight Designer!!!memberdefwebserver9-Apr-10 8:09 
Alan Beasley wrote:
Sounds like a plan, as I don't think Sacha would mind me choosing a ListBox or TreeView, as my next Control to Style.
And it may as well be for your application, as anything else I was thinking of.
 
I start looking into it...

 
I think I hear angels singing that a great day is coming...
 
Seriously, my point to the Programmers are that the Designers will save us all. The Designers still need us, but the end users want and will later DEMAND really really nice UI's.
 
The cool thing about the MVVM, is that you are not limited in any way to my "suggested" UI. You could decide to have the file display in a slider panel and the folders in a drop down if you wanted to.
GeneralRe: Excellent - & why I'm a Silverlight Designer!!!memberAlan Beasley9-Apr-10 8:50 
defwebserver wrote:
Seriously, my point to the Programmers are that the Designers will save us all. The Designers still need us, but the end users want and will later DEMAND really really nice UI's.

 
True - We need each other like never before!
 
In a way I used to hate doing application UI's, as previously you could only get access to it, right at the end of the project. As you know, bug fixes come first. And they have too, as it has to work to ship, but doesn't have to look pretty to ship!
 
This should all be changing - The worm has turned!!! (Whatever that means! Big Grin | :-D )
 
defwebserver wrote:
The cool thing about the MVVM, is that you are not limited in any way to my "suggested" UI. You could decide to have the file display in a slider panel and the folders in a drop down if you wanted to.

 
WARNING - BACK SEAT DESIGNER! Laugh | :laugh: Laugh | :laugh: Laugh | :laugh:
 
Nice suggestion, but I plan 2 surprise you, no peaking! (were not on first name MVVM's yet) Big Grin | :-D
 
In a normal project, I think it's better to resist initial external influence on design, as this tends to reduce the scope, by tunnelling all minds down one channel, less variety of input. Best to initially separate & come up with wildly different solutions to a problem. Grab the best from each, or combine...
 
So I might steal that idea, & I might not... Poke tongue | ;-P
 
Alan
GeneralRe: Excellent - & why I'm a Silverlight Designer!!!memberdefwebserver9-Apr-10 9:43 
Alan Beasley wrote:
In a normal project, I think it's better to resist initial external influence on design, as this tends to reduce the scope, by tunnelling all minds down one channel, less variety of input. Best to initially separate & come up with wildly different solutions to a problem. Grab the best from each, or combine...

 
I agree 100%. In this article:
http://openlightgroup.net/Blog/tabid/58/EntryId/87/Silverlight-MVVM-Enabling-Design-Time-Data-in-Expression-Blend-When-Using-Web-Services.aspx[^]
I suggest:
* Gather requirements 
* Create SketchFlows in Expression Blend to prototype the project 
* Create the Model and the View Model 
* Create the UI (the View)
 
But, when the UI is created, allowing the Designer to have full control of what is basically their responsibility is very important. I mean the Programmers would lose their minds if the Designers started moving around code "for Design purposes".
 
But the Programmers move and refactor Design elements all the time because up to now we had to to get the site into production.
 

Alan Beasley wrote:
WARNING - BACK SEAT DESIGNER!

 
See how we Programmers are... Smile | :)
GeneralRe: Excellent - & why I'm a Silverlight Designer!!!memberAlan Beasley10-Apr-10 1:53 
Excellent blog tutorial Michael,
 
It's all about the data, & a realistic design time to get creative with!
 
defwebserver wrote:
* Gather requirements * Create SketchFlows in Expression Blend to prototype the project * Create the Model and the View Model * Create the UI (the View)

 
I agree, & love the way Skecthflow aalows the designer to get involved at the start of a project! Cool | :cool:
 
defwebserver wrote:
I mean the Programmers would lose their minds if the Designers started moving around code "for Design purposes".

 
I don't know what you mean? Laugh | :laugh:
It should be easy to radically change the interation of that element just 1 day before release. Shouldn't it? Big Grin | :-D
 
defwebserver wrote:
But the Programmers move and refactor Design elements all the time because up to now we had to to get the site into production.

 
Don't look at me, I don't know how it works, you wrote it! Big Grin | :-D
But yes, you had no choice...
The designer just gave you a load of sticky labels to put on everything.
 
defwebserver wrote:
Alan Beasley wrote:
WARNING - BACK SEAT DESIGNER!
 
See how we Programmers are...

 
I couldn't possible comment. (there is no glass in my greenhouse! Big Grin | :-D )
GeneralAdditional info on MVVMmemberAlan Beasley10-Apr-10 8:07 
I'm sure you are aware of this Michael, but for the benefit of others regarding Model-View-ViewModel:
 
MVVM Model-View-ViewModel Video Tutorial [^]
 
A good explanation, & demonstration in Visual Studio, of the benefits of MVVM!!!
 
Recorded on the 28/8/08 by Jason Dolinger (90minutes long!!!)
 
Mainly for Developers, but well worth a watch for a Designer, or at least the first hour of it...
 
It is for WPF, but the principles are the same for Silverlight (as far as a designer is concerned anyway...)
 
P.S. As I designer, I did not follow all of coding stuff, as if I did, i'm in the wrong job! Big Grin | :-D
QuestionExcellent MVVM Overview - Question about Silverlight and .NET version...memberdmarley30-Mar-10 6:37 
This is a great article. Very nice, complete walkthough of MVVM concepts.
 
One Question: Are Silverlight 4 and .NET 4.0 required for this, or could it be made to work in Silverlight 3 and .NET 3.5?
 
In any case, thanks for the excellent article.
AnswerRe: Excellent MVVM Overview - Question about Silverlight and .NET version...memberdefwebserver30-Mar-10 6:54 
Thank you for the feedback.
 
The ability to use ICommand that allows the click on the Folder to load the files in the file details panel is a Silverlight 4/ Blend 4 feature only.
 
To do it in Silverlight 3 you would need to use a framework such as the "MVVM Light" framework or the "Cinch" framework.
 
Silverlight 4 will be released in about 30 days so... Laugh | :laugh:
GeneralRe: Excellent MVVM Overview - Question about Silverlight and .NET version...memberdmarley30-Mar-10 7:00 
That is what I figured, but wanted to verify. Thanks for the clarification.
GeneralGreat workmvpDaniel Vaughan30-Mar-10 3:34 
Hi Michael,
 
I liked that you used a page to perform the download. An enhancement might be to use an IHttpHandler, to bypass all the Page initialization etc.
Anyway, this is excellent work. Well done. Five from me.
 
Cheers,
Daniel
Daniel Vaughan
Twitter | Blog | LinkedIn | Projects: Calcium SDK, Clog

GeneralRe: Great workmemberdefwebserver30-Mar-10 3:42 
Thanks for the comments and the vote. I plan to make another part that handles uploads and that of course will use an IHttpHandler to handle large uploads.
 
We actually have a full Silverlight file manager at: http://silverlightbridge.net/[^] (with full source code of course) that uses a IHttpHandler for uploads.
 
This difference with this project is that it is about dong the same thing as silverlightbridge.net, but using MVVM.
GeneralGreat Stuff, but...memberDewey29-Mar-10 11:33 
Why in the world would any self respecting developer want to help a #$%&@ designer????
 
Just joking, this is what it's all about, and you've demonstrated it in a clear and concise fashion.
 
Good Work!!!
GeneralRe: Great Stuff, but...memberdefwebserver29-Mar-10 11:44 
Thanks for the laugh and your point is valid. Those darn Designers will make twice as much as the Programmers so why do they need our help Smile | :)
GeneralExcellentmvpPete O'Hanlon28-Mar-10 3:47 
Michael - this is an excellent example of using MVVM, and the explanation of the designer/developer split is clear and concise. Youv'e got my 5.

"WPF has many lovers. It's a veritable porn star!" - Josh Smith

As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

My blog | My articles | MoXAML PowerToys | Onyx



GeneralRe: Excellentmemberdefwebserver28-Mar-10 3:58 
Thank you for taking the time to leave a comment, it really makes it all worth it. I decided to just focus on the Designer/Developer aspect rather than testing and extensibility because my hope is that more Designers (the non-programming ones) will get into Silverlight simply because it gives them more control.
 
I really think this is a revolution.
 
I also hope some Designer starts with the base project I provided and comes up with a better interface than the one I have shown!
GeneralRe: ExcellentmvpPete O'Hanlon28-Mar-10 9:15 
This is a timely article. A MVVM focused subgroup of the WPF Disciples has just kicked off an entire debate around what comes first (the View or the ViewModel), and it's interesting seeing the split that something as seemingly innocuous as this has caused.

"WPF has many lovers. It's a veritable porn star!" - Josh Smith

As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

My blog | My articles | MoXAML PowerToys | Onyx



GeneralRe: Excellentmemberdefwebserver28-Mar-10 11:43 
Hmm that IS very interesting. It may sound odd, but I think having the Programmer make the ViewModel STILL limits the Designer.
 
The Designers must feel as if they can open Expression Blend and use the sample data features to make an app and then send it out to a Programmer to actually make the app work without having their UI that they worked so hard on messed up.
 
However, This article will mostly be read by Programmers who I hope will dangle this MVVM stuff in front of the Designers saying "Hey look what we're going to allow you to do". I wrote the article for the Programmers so that is why I put the ViewModel first.
 
Actually the best scenario I think is:
 
1) Gather Requirements
2) Make a full Sketchflow and decide exactly what the app is to be
3) Have the Programmer make the ViewModel
4) Have the Designer make the View
 
But I think people will usually do this:
 
1) Kinda come up with what the app should be
2) Make the View
3) Keep making changes to the View
4) Finally run out of time and send it off to the Programmer to make the ViewModel before you launch the next day Dead | X|
 
It must work in both directions Smile | :)
GeneralRe: ExcellentmemberZeroKoll28-Mar-10 18:11 
If you look at Blend's support for data, you will see that the designer can actually create fake viewmodels in the tool and bind to those during the design phase. This datasource then has to be rewritten as a VM before being able to use the app. but it lets the designer get started with everything without the developer. It does of course only work for data and not for functionality (commands). But automating the generation of the VM would be more or less impossible. It needs a dev. but being able to design with a datasource and then get the VM going, or doing it in parallell is nice. Just remember that the dev and designer (or the devigner) needs to agree on the interface so that the datasource that the designer/devigner uses looks the same as what the dev is building...
GeneralRe: Excellentmemberdefwebserver28-Mar-10 18:33 
Yes Blend does have a way to create "fake data" but I was unable to get fake data that could simulate the data for this file manager. I could create my own, but for the non-programmer designer that would be hard.
GeneralRe: ExcellentmvpPete O'Hanlon28-Mar-10 22:24 
defwebserver wrote:
but I think having the Programmer make the ViewModel STILL limits the Designer.

 
I disagree on this point, but I tend to prefer to have the VM created by an "integrator". It's their job to create the VMs in a way that does not stifle the designer, and also to liaise with the designer to ensure that they aren't attempting to do something that will cause problems with the application.
 
The key thing to support this is that there are a number of solid MVVM frameworks being created that support this delineation of responsibility. As the VM is more than just wiring up data to the view (e.g. it's the location to put code such as commanding or Mediator integration), it is vital that the developer must be involved at this stage. Here's how we tend to develop apps:
 
1. Work with the client to gather requirements/create use cases.
2. Generate basic screen flow diagrams using Sketchflow (which are integrated into the use cases).
3. Use the screen flows to form the basis of the views.
4a. Developers start to create VMs off the screen flow.
4b. Designer/integrator updates views as application development continues.
 
Following this approach allows us to be flexible, while also being able to demonstrate application flow/non persistent functionality from a very early stage. The important thing here, is that this approach works well for our business, there are other equally valid approaches that work better for other companies and the key is to find the balance that suits. What helps us is that our internal framework/tooling is suited for this particular approach to development.

"WPF has many lovers. It's a veritable porn star!" - Josh Smith

As Braveheart once said, "You can take our freedom but you'll never take our Hobnobs!" - Martin Hughes.

My blog | My articles | MoXAML PowerToys | Onyx



GeneralRe: Excellentmemberdefwebserver29-Mar-10 2:23 
Pete O'Hanlon wrote:
I disagree on this point, but I tend to prefer to have the VM created by an "integrator". It's their job to create the VMs in a way that does not stifle the designer, and also to liaise with the designer to ensure that they aren't attempting to do something that will cause problems with the application.

 
I see you point. In the end, the viability of he application must come first.
 
Pete O'Hanlon wrote:
1. Work with the client to gather requirements/create use cases.
2. Generate basic screen flow diagrams using Sketchflow (which are integrated into the use cases).
3. Use the screen flows to form the basis of the views.
4a. Developers start to create VMs off the screen flow.
4b. Designer/integrator updates views as application development continues.

 
I also agree with this. I find I am able to do this on my Open source projects (Sketchflow works great when you have a team that is not in the same location). However, when working at a large corporation I have had a lot of situations where they wont allow us to do it this way Mad | :mad: . That's why it is important that it works "both directions".
GeneralexcellentmemberMDL=>Moshu28-Mar-10 2:14 
Excellent man.
Many Thanks.
And 5000 from me!!!
GeneralRe: excellentmemberdefwebserver28-Mar-10 3:01 
Hey thanks a lot. Your comment is really appreciated.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130617.1 | Last Updated 1 Aug 2010
Article Copyright 2010 by defwebserver
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid