CodingTales

Programming and Computing facts by Mohammed Abdulsattar

Monday, February 8, 2010

Ultimate Theme Support in WPF MVVM Applications Using MEF

In MVVM, the Model or the ViewModel know nothing about the View making it pretty easy to change the View. But changing it after building your application is not what you can do with WPF alone (as far as I know). You can achieve this using Managed Extensibility Framework very easily. I've seen many applications providing theme support by including a various number of Resource Dictionaries. But this wouldn't modify the look and feel upside down. Using MEF, you can completely change the View of the application, not just the Resource Dictionaries.

I will use the the application that we built in my previous post, Creating a Complete Tabbed Inteface in WPF using MVVM. If you have read it or are confident that you can understand what it does, just by looking at source code ( it's very easy if you know a little about MVVM and WPF ), you can download it here and use it for this post. But if you don't think you can get it, I strongly recommend you read it.

Let's look at how we are going to implement it. We are going to have a folder called Themes which will have a lot of binaries (.dll) each representing a theme. Our application gets all the binaries when it starts and loads the theme, the name of which matches with the one stored in the application's settings. To achieve this, we are going to move the themes into a separate project.

Create a new WPF User Control library project (in the same solution) and name it DefaultTheme. Move the MainView.xaml to the DefaultTheme project and change the corresponding namespaces. Our code is still messed up, it won't compile. For this to run, the App class needs a MainView. We are going to give it using MEF. Add a reference the System.ComponentModel.Composition assembly from MEF to the TabbedLayout project. If you don't have it, download it at the CodePlex site of MEF. Now delete the App.xaml file; we are going to create our own. If you don't want to delete it, you can modify it and get our app running. But for this post, let's say you've deleted it. Create a new class App that derives from the Application class. Add the Main method that runs it.



class App : Application

{

    public static void Main(string[] args)

    {

        App app = new App();

        app.Run();

    }

}
Our application now runs (provided you've changed the namespaces correctly). But it does not show any window. To show a window, it needs a theme. By theme, we mean a name of the theme and a Window that can be used as the MainWindow of our application. Let's define an interface ITheme.




public interface ITheme

{

    public string Name { get; }

    public Window MainView { get; }

}
We need to implement this in the DefaultTheme so that it can be used in our application. Create a class DefaultTheme in the DefaultTheme project that implements the ITheme interface.




public class DefaultTheme : ITheme

{

    private MainView _mainView;

    public string Name

    {

        get { return "Default"; }

    }



public Window MainView

    {

        get { return _mainView ?? (_mainView = new MainView()); }

    }

}
Now, our application needs a theme. But, since our Themes folder can have a lot of themes in it, it would be better if we have a collection of Themes. A SelectedTheme will be used to launch the application.




public IEnumerable<ITheme> Themes { get; set; }

private ITheme _selectedTheme;
Now, we need to get the name of the theme from the settings of the application. Let's add a method Configure that does that and lauches the MainWindow.



[STAThread]

public static void Main(string[] args)

{

    App app = new App();

    app.Configure();

    app.Run();

}



private void Configure()

{

    if (Themes.Count() == 0)

    {

        MessageBox.Show("No theme is present. Application is shutting down");

        Shutdown();

        return;

    }



    string themeName = TabbedLayout.Properties.Settings.Default["ThemeName"] as string; //Get the theme name from settings

    _selectedTheme = Themes.SingleOrDefault(x =&gt; x.Name.Equals(themeName, StringComparison.OrdinalIgnoreCase)); //Get the theme with the above name from the collection



    if (_selectedTheme == null) //If there is no such theme, use the first theme in the collection

    {

        MessageBox.Show("The selected theme has been modified or removed. IncEditor will start with one of your available themes. You need to restart the application");

        _selectedTheme = Themes.First(x =&gt; true);

        TabbedLayout.Properties.Settings.Default["ThemeName"] = _selectedTheme.Name;

    }



    _selectedTheme.MainView.DataContext = new MainViewModel();

    MainWindow = _selectedTheme.MainView; //Set the MainWindow of the Application to the MainWindow of the selected theme

    _selectedTheme.MainView.Show();

}
We need to set the ThemeName setting in our application. Right Click the TabbedLayout project in the Solution Explorer and select Properties. Add a new User setting ThemeName and set its value to Default. We are going to use the Default theme.

Now our application is all ready, except that it does not have the Themes collection. We haven't initialized it yet. Now, we need MEF to load all the assemblies from the Themes folder and add all the IThemes to the collection. To do this, we need to add an ImportManyAttribute on the Themes collection in the App class.



[ImportMany(typeof(ITheme))]

public IEnumerable<ITheme> Themes { get; set; }
We need to export the DefaultTheme class from the DefaultTheme project. Add an



[Export(typeof(ITheme))]

public class DefaultTheme : ITheme
Now we need to do the MEF stuff, create a container, add a catalog to it and compose the parts. If you don't know what this is, refer to the Documentation on the Codeplex site of MEF. You need to create a folder Themes in the TabbedLayout project.



private void Compose()

{

    var catalog = new DirectoryCatalog(@"..\..\Themes");

    var container = new CompositionContainer(catalog);

    container.ComposeParts(this);

}
Call this method before Configure.



private void Configure()

{

    Compose();
Now run the application and you will see a MessageBox popping up saying no theme is present and the application shuts down. It's reasonable because you don't have any theme in the Themes folder. Now all you need to create is copy the DefaultTheme.dll into the themes folder and run the application again. This time it runs perfectly well as if nothing ever happened. But you've added great functionality to it. You can create another theme, add it to the Themes folder, change the ThemeName property and run your application using that theme. You can even display a list of all the themes available to the user and allow him to change it. I've done it in an open source project IncEditor. It would be very nice of you if you join it and give your valuable ideas so that nutters like me can increase our knowledge and brag about on blogs as I've been doing throughout this post. Wishing you good luck!

Saturday, February 6, 2010

Creating a complete Tabbed interface in WPF using MVVM

Tabbed user interfaces are very common. Building them in WPF is very easy. But MVVM makes it a little tougher. And, if you can build a one in MVVM, you've probably covered half the distance to the road on learning MVVM.

If you're new to MVVM, you should have a look my previous post, Getting Started With MVVM in WPF. This post assumes that you know a little about MVVM.

You can download code here.

I've written this article for people like me who can't understand Josh Smith's article on MSDN very easily. If you think you can understand it, you better read it.

Let's have a look at our requirements:

  • A menu with "New Tab", "Close Current Tab" and "Exit" options

  • A TabControl in which tabs appear. The tab headers should have a close button.

  • Ctrl + N should create a new tab and Ctrl + F4 should close the current tab. Ctrl + X should close the application.


Well, this seems to be a pretty simple application. For this, you'd need an MVVM framework. You can create your own (I've shown you how to create a simple one in my previous post) or use an open-source one. I prefer MVVM Toolkit (It has an installer only for VS2008. VS 2010 Beta 2 users can download the code here). Now, if you've installed it, create a new Model-View application and name it TabbedLayout. It gives you a MVVM solution structure and a Delegate Command. Press F5 to see it running.

You see that it already has a menu and the "Ctrl + X to close" functionality. But we do not need that Grid. Instead we need a TabControl. Replace it with a TabControl.

[xml]<TabControl />[/xml]

Now we need a collection of TabItems that can be bound to the TabControl. We saw how to implement it in the previous post. But, have a closer look here. If we are maintaining an ObservableCollection of TabItems, we are telling the ViewModel that the View uses a TabControl. So, the ViewModel does know something about the View. This wouldn't be purely MVVM. In order for our application to be purely MVVM, our ViewModel should expose a collection of ViewModels that the View renders. Let's implement this.

We need a new ViewModel that will be shown as a TabItem (or something of your choice) in the View. Let's call it WorkspaceViewModel. Create a new class in the ViewModels folder and name it WorkspaceViewModel. Since, a tab will have a Header, we add a property Header to our class. Note that it inherits from the ViewModelBase class, and the Header property raises the PropertyChanged event.

[csharp]
public class WorkspaceViewModel : ViewModelBase
{
private string _header;
public string Header
{
get { return _header; }
set
{
_header = value;
OnPropertyChanged("Header");
}
}
}
[/csharp]

The MainViewModel maintains a list of WorkspaceViewModels. Create a new public property and initialize it from the constructor.

[csharp]
public ObservableCollection<WorkspaceViewModel> Workspaces { get; set; }

public MainViewModel()
{
Workspaces = new ObservableCollection<WorkspaceViewModel>();
}
[/csharp]

Now the TabControl needs to be bound to this collection.

[xml]<TabControl ItemsSource="{Binding Workspaces}" />[/xml]

Now, we have a TabControl and a collection of tabs. Now, if you add/remove from the Workspaces collection, the changes get reflected in the view. But, there is nothing in the view or the ViewModel that adds/removes Workspaces from the collection. Let's create a NewWorkspaceCommand in the ViewModel that adds a new Workspace to the Workspaces collection. A MenuItem in the View can be bound to the command to add a new Workspace. Add this code to the MainViewModel.

[csharp]
private DelegateCommand _newWorkspaceCommand;
public ICommand NewWorkspaceCommand
{
get { return _newWorkspaceCommand ?? (_newWorkspaceCommand = new DelegateCommand(NewWorkspace)); }
}

private void NewWorkspace()
{
Workspaces.Add(new WorkspaceViewModel { Header = "New Workspace" });
}
[/csharp]

Now, let's create a new MenuItem that binds its Command to the NewWorkspaceCommand. Add this MenuItem under the File MenuItem.

[xml]<MenuItem Command="{Binding NewWorkspaceCommand}" Header="_New Tab" />[/xml]


Press F5 and run the program. Click the "File" Menu and then "New Tab". You see a tab is added to the TabControl. Click it to bring focus on it. You see that the Header and the Content of the TabItem are "TabbedLayout.ViewModels.WorkspaceViewModel". What's this? You may be freaking out, but before you blame WPF or MVVM or me, ask yourself, did you tell the View how to render a WorkspaceViewModel? WPF can't assume what to display! It does what you tell it to do. If WPF does not how to render an element, it simply calls it ToString method and renders it. So what you see is justified. But you do need your users to see that. You'd present them with something more interesting. You need to tell WPF how to render a WorkspaceViewModel. You'll need DataTemplate to do that.

For the TabHeader, let's display a TextBlock. The text of the TextBlock will be the Header property of the WorkspaceViewModel. Modify the TabControl to look like this. It's simple: we set the ItemTemlate property of the TabControl to a DataTemplate which displays the TextBlock.

[csharp]
<TabControl ItemsSource="{Binding Workspaces}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}" />
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
[/csharp]

Run the Program and you'll see that the Tab Header has changed. It now shows "New Workspace". But the content is still the same. We need to tell the View what to do with a WorkspaceViewModel. Let's create a new DataTemplate for type WorkspaceViewModel and have it display again a TextBlock. Add the following code to the Window.Resources section.

[csharp]
<DataTemplate DataType="{x:Type vm:WorkspaceViewModel}">
<TextBlock Text="Hello to Tabbed Layout!" />
</DataTemplate>
[/csharp]


You need to add a reference to the assembly in the Window tag:
[xml]xmlns:vm="clr-namespace:TabbedLayout.ViewModels"[/xml]

Run the application and see it running smoothly. But there's some problem. When, you want add a new tab, it should get focused. If it were a simple TabItem, you would have called the Focus() method on it. But here, you need a different approach. Let's maintain a SelectedIndex property which gives you the index of the Workspace to be focused and the TabControl can bind it's SelectedIndex property to it.

[csharp]
private int _selectedIndex = 0;
public int SelectedIndex
{
get { return _selectedIndex; }
set
{
_selectedIndex = value;
OnPropertyChanged("SelectedIndex");
}
}
[/csharp]
We need to update the SelectedIndex property when a new workspace is added.
[csharp]
private void NewWorkspace()
{
var workspace = new WorkspaceViewModel { Header = "New Workspace" };
Workspaces.Add(workspace);
SelectedIndex = Workspaces.IndexOf(workspace);
}
[/csharp]
And then bind the SelectedIndex property of the TabControl to the SelectedIndex of the ViewModel.
[xml]<TabControl ItemsSource="{Binding Workspaces}" SelectedIndex="{Binding SelectedIndex}">[/xml]

This makes closing a workspace easier ( That's why I haven't discussed it till now). Let's create a new command in the MainViewModel that removes the selected workspace from the Workspaces collection and bind a MenuItem to this command. There's one more point to be discussed: if there is no Workspace open, the command must not execute. We can go as far as disabling the MenuItem if there is no Workspace open. We must also set the SelectedIndex to point to another open tab.

[csharp]
private DelegateCommand _closeWorkspaceCommand;
public ICommand CloseWorkspaceCommand
{
get{return _closeWorkspaceCommand ?? (_closeWorkspaceCommand = new DelegateCommand(CloseWorkspace, ()=>Workspaces.Count > 0));}
}
private void CloseWorkspace()
{
Workspaces.RemoveAt(SelectedIndex);
SelectedIndex = 0;
}
[/csharp]

The CloseWorkspaceCommand delegates the task of removing the the Workspace to the CloseWorkspace only if Workspaces.Count > 0. Now, we need to bind a new MenuItem to this command:
[xml]<MenuItem Command="{Binding CloseWorkspaceCommand}" Header="_Close Tab" />[/xml]

Now run the application and see it is running perfectly fine. Let's add some shortcuts. All we need to do is create input bindings in the window.

[xml]
<KeyBinding Key="N" Modifiers="Control" Command="{Binding NewWorkspaceCommand}" />
<KeyBinding Key="F4" Modifiers="Control" Command="{Binding CloseWorkspaceCommand}" />
[/xml]

Let's indicate the shortcuts in the MenuItems.
[xml]
<MenuItem Command="{Binding NewWorkspaceCommand}" Header="_New Tab" InputGestureText="Ctrl + N" />
<MenuItem Command="{Binding CloseWorkspaceCommand}" Header="_Close Tab" InputGestureText="Ctrl + F4" />
[/xml]

Now, we are done with the tabbed layout. Run the application and check out what it does.

The last thing left out is the "Close" button on the Tab Headers. Let's try to implement it. Naturally, the Close button must be bound to a command. Since, it will be on a TabItem whose DataContext is the WorkspaceViewModel, we need to create the CloseCommand in the WorkspaceViewModel.

[csharp]
private DelegateCommand _closeCommand;
public ICommand CloseCommand
{
get { return _closeCommand ?? (_closeCommand = new DelegateCommand(CloseWorkspace);}
}

private void CloseWorkspace()
{
throw new NotImplementedException();
}
[/csharp]

Here we have a problem. Our CloseWorkspaceCommand is in the WorkspaceViewModel and it is the MainViewModel that holds the Workspaces collection. How can it remove itself from the collection without having a reference to it? We can pass the MainViewModel in the constructor of the WorkspaceViewModel so that it has a reference to it. But, there is a more elegant solution. The CloseWorkspace command raises an event, RequestClose which the MainViewModel listens to and removes the sender of the event from the collection. This way, we need not introduce between WorkspaceViewModel and MainViewModel. Replace the CloseCommand which you added above with the following command an EventHandler.

[csharp]
private DelegateCommand _closeCommand;
public ICommand CloseCommand
{
get { return _closeCommand ?? (_closeCommand = new DelegateCommand(OnRequestClose);}
}

public event EventHandler RequestClose;
private void OnRequestClose()
{
if (RequestClose != null)
RequestClose(this, EventArgs.Empty);
}
[/csharp]

Now, the MainViewModel must listen to the RequestClose event of every Workspace in Workspaces collection. And if we add or remove Workspaces, it must act accordingly. The simplest way to do this is to listen to the CollectionChanged event of the Workspaces collection and subscribe to the events of the NewItems and unsubscribe to the events of the OldItems. Modify the constructor and add event handlers as follows:

[csharp]
public MainViewModel()
{
Workspaces = new ObservableCollection<WorkspaceViewModel>();
Workspaces.CollectionChanged += Workspaces_CollectionChanged;
}

void Workspaces_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null && e.NewItems.Count != 0)
foreach (WorkspaceViewModel workspace in e.NewItems)
workspace.RequestClose += this.OnWorkspaceRequestClose;

if (e.OldItems != null && e.OldItems.Count != 0)
foreach (WorkspaceViewModel workspace in e.OldItems)
workspace.RequestClose -= this.OnWorkspaceRequestClose;
}

private void OnWorkspaceRequestClose(object sender, EventArgs e)
{
CloseWorkspace();
}
[/csharp]

Note that we already have a CloseWorkspace method that removes the workspace. Now, we have a CloseCommand in the WorkspaceViewModel that has the capability to close itself. But, we haven't bound the command to any element in the View. Let's add a button to the Header of the TabItem and bind it's Command property to the CloseCommand of the WorkspaceViewModel. Replace the TabControl with this code.

[csharp]
<TabControl ItemsSource="{Binding Workspaces}" SelectedIndex="{Binding SelectedIndex}">
<TabControl.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Header}" />
<Button Command="{Binding CloseCommand}" Content="X" Margin="4,0,0,0" FontFamily="Courier New" Width="17" Height="17" VerticalContentAlignment="Center" />
</WrapPanel>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
[/csharp]

And, finally run it. You'll see a button beside the Header text of the TabItem. Click the button to close the tab. We, now have a fully functional application with Tabbed Layout implemented in MVVM. It has all the features we discussed at beginning. But there is something missing. When you close a TabItem, the first tab gets focused. You can change that to focus the previous Tab that was focused. I leave that to you.

You can now check out Josh Smith's article now and understand it easily. There's something more in it than would have been appropriate for this post. Now, I take a leave wishing you once again good luck in the amazing world of WPF and MVVM.

Tuesday, January 12, 2010

Getting started with MVVM in WPF

I've been working with MVVM and WPF for a couple of weeks now. I decided to log what I've learned here. Here goes a getting started tutorial with MVVM.

  • Download the source code here


The Model-View-ViewModel pattern was introduced by John Gossman to effectively utilize the functionality of WPF. Since then, MVVM has been used in a number of WPF applications with very impressive results.
MVVM has three components:

  • Model: It is your data or classes that represent entities in your application. It normally contains no WPF-specific code.

  • View: This is the User Interface element visible to the user. Its DataContext is its ViewModel.

  • ViewModel: It contains all the data that needs to be displayed and procedures to modify the model at will. The magic about MVVM is that the ViewModel knows nothing about the View.


You see that this is very loosely coupled. The View knows the ViewModel but the ViewModel does not know the View. You can very easily replace the View without affecting the ViewModel. This is very useful in Developer/Designer teams where the Developer improves the ViewModel and the Designer enhances the View.

The fact that the ViewModel does not know anything about the View comes as a bit of surprise. There is one more surprise – a typical View in MVVM does not need have a code-behind (except for the general boiler-plate code that calls the InitializeComponent() method from the constructor)!

You may be wondering how the view updates itself when the ViewModel changes and how it handles user interaction like button clicks etc. This is what makes MVVM specific to WPF.

The controls in the View bind themselves to the corresponding properties in the ViewModel. The changes in ViewModel will be reflected in the view, thanks to Data Binding in WPF. (Otherwise we would have had to handle every event and then update the view accordingly.)

As for user interaction, we always have had commands in WPF. MVVM leverages on this feature. Instead of writing event handling code for button clicks, we bind the buttons (or MenuItems) to Commands in the ViewModel. Every button (even the SaveCustomer, CloseTab etc.) binds itself to a command which the ViewModel exposes. This command delegates its job to a method in the ViewModel that gets the work done. But the problem is that there is no built-in command in WPF that does that. We have a RoutedCommand that targets UIElements but not methods. Here comes to the scene a new command that targets methods, the DelegateCommand or the RelayCommand. Controls can bind the RelayCommand (that the ViewModel exposes) and invoke methods in the ViewModel.

The DelegateCommand implements the ICommand interface and delegates the Execute and CanExecute methods in the interface to methods in the ViewModel.

[csharp]
using System;
using System.Windows.Input;

namespace MvvmSample
{
public class DelegateCommand : ICommand
{
readonly Action&lt;object&gt; _execute;
readonly Predicate&lt;object&gt; _canExecute;

public DelegateCommand(Action&lt;object&gt; execute) : this(execute, null)
{
}

public DelegateCommand(Action&lt;object&gt; execute, Predicate&lt;object&gt; canExecute)
{
if (execute == null)
throw new ArgumentNullException(&quot;execute&quot;);

_execute = execute;
_canExecute = canExecute;
}

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

public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}

public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
}
[/csharp]

Now we are going to create a simple tabbed interface. When you File->New Tab, a new tab opens up. When you click File->Exit, the application closes. You may think that this is very simple but achieving this in MVVM needs a lot of ground on it.

Open a new WPF application. Change the Window1 to MainWindow (I just hate Window1). Replace the Grid element in the MainWindow with the following markup.

[xml]
&lt;DockPanel&gt;
&lt;Menu DockPanel.Dock=&quot;Top&quot;&gt;
&lt;MenuItem Header=&quot;_File&quot;&gt;
&lt;MenuItem Header=&quot;New _Tab&quot; /&gt;
&lt;Separator /&gt;
&lt;MenuItem Header=&quot;E_xit&quot; /&gt;
&lt;/MenuItem&gt;
&lt;/Menu&gt;
&lt;TabControl /&gt;
&lt;/DockPanel&gt;
[/xml]

You know it simply adds a menu to the top and a tab control. Now we create a simple MainWindowViewModel class. Since the View binds its controls to the Properties in the ViewModel, we need to implement the INotifyPropertyChanged interface. But in this example we are not going to need it. Create an empty class MainWindowViewModel.

We know that the view sets its DataContext to the ViewModel. We’ll use the Application class to set it for the view. Remove the StartupUri attribute from the Application.xaml file and override the OnStartup method to initialize a new MainWindow and a new MainWindowViewModel, set the DataContext of the MainWindow to the MainViewModel, set the MainWindow property of Application class this MainWindow and finally show the MainWindow.

[csharp]
protected override void OnStartup(StartupEventArgs e)
{
MainWindow mainWindow = new MainWindow();
MainWindowViewModel mainWindowViewModel = new MainWindowViewModel();
mainWindow.DataContext = mainWindowViewModel;
base.MainWindow = mainWindow;
mainWindow.Show();
}
[/csharp]

Now we have setup the base for MVVM. But our application does nothing. When we click New Tab or Exit nothing happens. To hook this up, we need a command. Let’s first implement the Exit Command. In the MainWindowViewModel, add a new DelegateCommand, ExitCommand.

[csharp]
private DelegateCommand exitCommand;
public ICommand ExitCommand
{
get
{
if(exitCommand == null)
exitCommand = new DelegateCommand(Exit);
return exitCommand;
}
}

private void Exit(object obj)
{
Application.Current.Shutdown();
}
[/csharp]

Now when the Execute() method on ExitCommand is called, Exit method is invoked. We use the Exit method to shutdown the application. Now all we have to do is bind the Exit menu item to this command. When you click Exit, the Exit method is called and the application shuts down.

[xml]&lt;MenuItem Header=&quot;E_xit&quot; Command=&quot;{Binding ExitCommand}&quot; /&gt;[/xml]

Now, let’s implement the Add Tab functionality. Obviously, we need a new command, AddTabCommand.

[csharp]
private DelegateCommand addTabCommand;
public ICommand AddTabCommand
{
get
{
if (addTabCommand == null)
addTabCommand = new DelegateCommand(AddTab);
return addTabCommand;
}
}

private void AddTab(object obj)
{
throw new NotImplementedException();
}
[/csharp]

Here we have a problem. The ViewModel does not know the View and does not know the TabControl in it. How is it going to add a tab into that TabControl? If it were a simple code-behind, we would have given the tab control a name and hooked up an event handler to add a new tab to the control. But what do we do now? Any guesses?

Let’s use a trick. We know the View can modify itself to reflect changes in the ViewModel. Let’s exploit this. We will maintain a list of tabs in the ViewModel and the TabControl binds itself to this list. Now if we add a new item in the list, a new tab is added in the view! Wonderful!

[csharp]
public ObservableCollection&lt;TabItem&gt; Tabs { get; set; }

public MainWindowViewModel()
{
Tabs = new ObservableCollection&lt;TabItem&gt;();
}
[/csharp]

We need an observable collection to bind lists (It’s why we did not need to implement the INotifyPropertyChanged explicitly here). Now, we need to bind the TabControl to this collection.

[xml]
&lt;TabControl ItemsSource=&quot;{Binding Tabs}&quot; /&gt;
[/xml]

Now, the AddTab method adds a new TabItem into the list and the View updates itself.

[csharp]
private void AddTab(object obj)
{
TabItem tab = new TabItem();
tab.Header = &quot;New Tab&quot;;
Tabs.Add(tab);
tab.Focus();
}
[/csharp]

The last thing to do is to hook up the Add Tab MenuItem to the AddTabCommand.

[xml]
&lt;MenuItem Header=&quot;New _Tab&quot; Command=&quot;{Binding AddTabCommand}&quot; /&gt;
[/xml]

Excellent! It’s all working very well. This is all about MVVM in its simplest way. You can see how easy it is to have everything separated and implement a very loosely coupled application. MVVM lets you unit test you software and change the views very easily.

You can notice that in this example, the ViewModel does know something about the View. It knows that the view contains a TabControl and adds TabItems to it. You can remove even this dependency (See my next post, Creating a Complete Tabbed Interface in MVVM). Now that you have set for yourself a base, explore the fantastic world of WPF and MVVM. Good Luck!

Monday, December 28, 2009

Microsoft Student Programs

Everyone who knows "Computer" knows "Microsoft" and every techie would look forward to work in it. Every student would like to master its technologies. It'd be very cruel of Microsoft not to include Students in it. Students are those who develop something that people now haven't even dreamt of. Microsoft surely can't ignore them.

Microsoft has many student programs that connect it to the students. It's mission is to empower students to achieve their hopes and dreams. Here is a small list of its prominent initiatives:

[caption id="attachment_32" align="alignleft" width="230" caption="Imagine Cup Poland 2010"]Imagine Cup Poland 2010[/caption]

Imagine Cup is challenge for students worldwide and draws their talent, creativity and passion towards technology and helps them make a difference in the world. The Imagine Cup 2010 finals will be held in Poland and there are five Competitions: Software Design, Embedded Development, Game Design, Digital Media, IT Challenge. Winners in each category will be awarded exciting prizes. You must register for Imagine Cup is you're enthusiastic about technology. (Please use my referral code while registering: codingtales)

[caption id="attachment_30" align="alignleft" width="202" caption="/Student"]/Student[/caption]

/STUDENT has everything to do with students. Students will find all they need, free software, discounted software, learning materials, news about latest technology, projects to participate in and everything they ever dreamed of doing. There is Windows 7 at $29.99! There is an all new Student Lounge for all the students with stuff related to students. You'll be blown up with all that /STUDENT has to offer. Do not hesitate for a second before you jump into it: A computer science student who is not connected to /STUDENT is not a student.

[caption id="attachment_33" align="alignleft" width="166" caption="Microsoft Student Partners"]Microsoft Student Partners[/caption]

Microsoft Student Partners are the most technical students in the world. They have exclusive access to technology; they coach their friends about new technologies; they know more than any other student about technology; they get a chance to work in Microsoft; they attend conferences with special privileges; they are just awesome!

I'd like to make an announcement here: I've been selected as a Microsoft Student Partner this year!

[caption id="attachment_31" align="alignleft" width="125" caption="Microsoft Dreamspark"]Microsoft Dreamspark[/caption]

Microsoft Dreamspark just provides software to students. Mind you, it's not normal software. Here goes the list:

Visual Studio 2010 Ultimate Beta 2
Visual Studio 2008 Professional
SQL Server 2008 Developer
Windows Server 2008 (R2) Standard
Robotics Developer Studio 2008 R2
and lots more...

Being a student does not need more benefits!



[caption id="attachment_34" align="alignleft" width="166" caption="Student Tech Clubs"]Student Tech Clubs[/caption]

Student Tech Clubs is a stop to organize tech clubs. You start a tech club and discuss technology among your friends. This way you make more friends and be a master in technology. You can collaborate with your friends and build software that you've been dreaming about and the world would be left wowing about. It's your chance to show yourself off!

Well students, this is what you must participate in it. If you don't you're really not a student. All the best with Microsoft.

Thursday, July 30, 2009

ASP.NET MVC Vs ASP.NET Web Forms

Since when Microsoft released ASP.NET MVC in January 27 2009, there has been a lot of debate on this topic — Is ASP.NET MVC better than ASP.NET Webforms? Many developers think that Microsoft has taken a step behind, towards the days of classic ASP, by releasing ASP.NET MVC. But some argue that it will eventually replace Web Forms. But as far as I know, none is true.

ASP.NET MVC uses the Model-View-Controller design pattern and does not use the server controls that Web Forms uses. Many developers were quickly attracted to ASP.NET when it was introduced in 2001 mainly because the Web Forms provided Rapid Application Development ( RAD ). They said that the design was a bit complex and confusing for a newbie but once mastered it’s very easy. ASP.NET MVC removed the much hyped server controls and provided a clean MVC pattern to deal with the UI.

Advantages of Web Forms

  1. Rapid Application Development

  2. Very rich server controls

  3. Easy data binding

  4. Improves over the stateless protocol of HTTP


Advantages of MVC Model

  1. The MVC pattern, by itself!

  2. Separation of Concerns

  3. SEO friendly URLs

  4. Full control over HTML


Disadvantages of Web Forms

  1. The complex design

  2. TheViewstate sometimes reaches large values

  3. Does not generate clean HTML

  4. No separation of concerns


Disadvantages of ASP.NET MVC

  1. Uses the same stateless HTTP

  2. No support for the Server controls that provide the RAD


Which one to choose?

It’s your choice entirely! Choose what is the functionality that you need most, cleaner development or rapid development.

As of me, I’ve chosen ASP.NET MVC. Some of you may be thinking I am wrong because I lose the RAD part. But I’ve a justification for that. I must have lost the famous GridView, but I’d like to tell you that I never liked it! There are many server controls that I’ve never used. I’ve more importantly used the simple ones like <asp:TextBox>, <asp:Label> etc. Making my design more complex and losing my control over the HTML I (ought to) generate is not compensated by those server controls? ASP.NET MVC gives me much better. If you like ASP.NET Web Forms, I’d advise you to shift to ASP.NET MVC and ake a little trouble by yourself and make your customers happy. If you don’t like Web Forms, wait for my tutorial on a simple ASP.NET MVC application! I’ll be posting it soon enough. Till then do some googling for a while and get started.

Saturday, July 25, 2009

Google Wave – Yet another *hot* product from Google

[caption id="" align="alignleft" width="360" caption="Google Wave"]Google Wave[/caption]

Google has announced another wonderful tool that enables you to stay in touch with your friends more easily than ever before – Google Wave. This another tool from Google is sure to hand over online communication in it’s hands. Google could have a long list of reasons behind that or it could be just one more attempt to take over Facebook, Twitter and all since it’s Orkut is not that popular.

Google Wave is going to be bundled with a whole lot of new features that no application I know has. Google says that all the action happens as a Wave. You create it, you and your friends modify it so that you and all your friends can see it. That sounds pretty simple but Wave has many things in it to create and modify. A wave can contain

  1. Richly formatted text

  2. Photos

  3. Gadgets

  4. Feeds

  5. And many more things (yet to be built!)


The main thing that makes it stand out from the rest is its concurrency. Any number of users can edit the Wave simultaneously and everyone will have their wave updated as the editor edits it. You can also rewind to see how the changes got effected. This is really a cool functionality that no application has.

However it’s going to be released on September 30 of this year only to a 100,000 special invites. It is perhaps going to adopt the GMail invite feature. But those 100,000 special invites are going to be very lucky.

Google Wave is completely open source so that the Developer community can dig in and do something that even Google couldn’t do ( Google doesn’t say that but it translates to the same )! Even a plugin for Wordpress is being developed.

Whatsoever, Google Wave, according to the hype it currently is creating, is going to make Google the real monarch of internet communcation.

About Me

My photo
I'm a computer science engineering student with a lot of passion for computers.