UnicornManager: Prism 4, MEF, WPF, EF 4.1 code first, NuGet, MVVM, DataValidation, …

This blog post is an attempt to learn and discover Prism 4 together with MEF, EF 4.1 code first and by trying to use concepts like a repository, data validation and Unit of Work.

The reason why I post this here is to (1) learn from your comments and (2) create a basic guided tutorial for beginners.

I hope you don’t mind that I’ve chosen unicorns for this example ;)

Go!

Let’s start Visual Studio 2010 Service Pack 1 and create a new WPF Application called UnicornManager:

The solution will contain 3 projects at the end:

  • UnicornManager
  • UnicornManager.Core
  • UnicornManager.Data

UnicornManager.Core will be our core module, hence the name.
The first thing that we are going to do is preparing our UnicornManager project so that it can import other modules via MEF.

First we are going to add some references.
Right-click UnicornManager and select [Add Reference…] and search for System.ComponentModel.Composition in the [.NET] tabpage.

Next we need to install Prism with MEF. Make sure the UnicornManager project is selected and in Visual Studio click [Tools] > [Library Package Manager] > [Manage NuGet Packages…]
Click [Online] on the left and in the [Search Online] textbox type in: Prism.
Select Prism.MEFExtensions and click [Install].
(This will automatically also install Prism, because it depends on it)

Now rename MainWindow.xaml to Shell.xaml by right-clicking it and [Rename].
Open the Shell codebehind file (Shell.xaml.cs) and also rename MainWindow to Shell.

Above the partial Shell class add the [Export] attribute.

The codebehind for Shell should look like this now:

namespace UnicornManager
{
/// <summary>
/// Interaction logic for Shell.xaml
/// </summary>
[Export]
public partial class Shell : Window
{
public Shell()
{
InitializeComponent();
}
}
}

Now in the Shell xaml code we will create a very basic layout. We have a region to show our content and on the left a region for the sidebar. I have called these two regions MainRegion and SidebarRegion where our Views (UserControls) will be made visible. For the regions I’m using two ContentControls, but don’t forget that an ItemsControl also exists to host multiple UserControls in it.

This is the XAML:

<Window x:Class="UnicornManager.Shell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Regions="http://www.codeplex.com/prism">http://www.codeplex.com/prism"
Title="Shell" Height="600" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<ContentControl x:Name="MainRegion"
Regions:RegionManager.RegionName="MainRegion"
Grid.Column="1" />

<ContentControl x:Name="SidebarRegion"
Regions:RegionManager.RegionName="SidebarRegion"
Grid.Column="0" />
</Grid>
</Window>

Add a new class to the UnicornManager project and name it CoreBootstrapper.cs.
This class will be the starting point of our application.

Make the class public and let it inherit from MefBootstrapper.
The other methods are being used to tell our application which is our main Window to start up and where our other Views and objects  are located.

The bootstrapper code looks like this:

namespace UnicornManager
{
public class CoreBootstrapper : MefBootstrapper
{
protected override System.Windows.DependencyObject CreateShell()
{
return this.Container.GetExportedValue<Shell>();
}

protected override void InitializeShell()
{
base.InitializeShell();
Application.Current.MainWindow = (Window)this.Shell;
Application.Current.MainWindow.Show();
}

protected override void ConfigureAggregateCatalog()
{
base.ConfigureAggregateCatalog();
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(CoreBootstrapper).Assembly));
}
}
}

Now if you try to run the project you will receive an IOException that the resource ‘mainwindow.xaml’ cannot be located. Don’t worry, we just forgot to remove the startup path from the App.xaml code:

<em> </em>StartupUri="MainWindow.xaml"

Now in the App codebehind tell the application that it should use our bootstrapper instead:

public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);

CoreBootstrapper bootstrapper = new CoreBootstrapper();
bootstrapper.Run();
}
}

If everything went fine, you should be able to run the application. :D

Now add a new Class Library project called UnicornManager.Data to the solution. This project will contain our models by using the Entity Framework 4.1 code first.

Delete Class1.cs from the project and create two folders: DAL and Models.
(DAL = Data Access Layer)

Make sure you have the Data project selected and install EntityFramework via NuGet:

Add also the System.ComponentModel.Composition reference to the project.

Lets create our simple model by adding a new Unicorn class to the Models folder. Here is the code:

namespace UnicornManager.Data.Models
{
public class Unicorn
{
public int UnicornId { get; set; }

public string LastName { get; set; }
public string FirstName { get; set; }
}
}

In the DAL folder we are going to add some repositories, UnitOfWork and code necessary for EF 4.1 code first. I’m not posting the code here, you can download this and check the DAL folder in the UnicornManager.Data project.

Because this is just a basic demo application with one class, we would not need a UnitOfWork because it is just an extra wrapper around the UnicornRepository. However if you have more models you will have some extra Repositories, which can be placed in the UnitOfWork.

Our last step is to create our Core module. Add a new Class Library project to the solution called UnicornManager.Core. This will contain our ViewModels and Views.

Delete Class1.cs and add a new class called CoreModule.cs.
Remember we also need to add Prism here by getting the Prism.MEFExtensions from NuGet and a reference to System.ComponentModel.Composition and System.Xaml.

The CoreModule is the entry point for our Bootstrapper. Here we Export our module and register our Views with the regions of our Shell.
This is the code:

[Module(ModuleName = "CoreModule")]
[ModuleExport(typeof(CoreModule))]
public class CoreModule : IModule
{
private IRegionManager _RegionManager;

[ImportingConstructor]
public CoreModule(IRegionManager regionManager)
{
this._RegionManager = regionManager;
}

#region IModule Members

public void Initialize()
{
_RegionManager.RegisterViewWithRegion("MainRegion", typeof(Views.MainView));
_RegionManager.RegisterViewWithRegion("SidebarRegion", typeof(Views.SidebarView));
}

#endregion
}

In the Initialize method, we register two views, but we didn’t create them yet, time to do this first.

Add two folders in the Core project: ViewModels and Views.
In the ViewModels folder add two classed called: MainViewModel.cs and SidebarViewModel.cs.

Code for MainViewModel:

namespace UnicornManager.Core.ViewModels
{
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class MainViewModel : NotificationObject
{
private IUnitOfWork _UnitOfWork;

[ImportingConstructor]
public MainViewModel(IUnitOfWork unitOfWork)
{
this._UnitOfWork = unitOfWork;
Init();
}

public ObservableCollection<Unicorn> Unicorns { get; set; }

private void Init()
{
this.Unicorns = _UnitOfWork.UnicornRepository.GetSyncedEntityItems();
}
}
}

Don’t forget to add a reference from the Core to the Data project. Here we see that we get our UnitOfWork object via MEF by using the [ImportingConstructor] attribute.

We also inherit from NotificationObject, this way we don’t have to implement the INotifyPropertyChanged ourselves. Thank you Prism for adding this already to the ViewModels base class.

Code for the SidebarViewModel:

namespace UnicornManager.Core.ViewModels
{
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class SidebarViewModel : NotificationObject, IDataErrorInfo
{
private IUnitOfWork _UnitOfWork;
private DelegateCommand<object> _AddUnicornCommand;

private string _FirstName;
private string _LastName;

[ImportingConstructor]
public SidebarViewModel(IUnitOfWork unitOfWork)
{
_UnitOfWork = unitOfWork;
_AddUnicornCommand = new DelegateCommand<object>(AddUnicornExecute,
(o) => { return !string.IsNullOrEmpty(FName) && !string.IsNullOrEmpty(LName); });
PropertyChanged += new PropertyChangedEventHandler(SidebarViewModel_PropertyChanged);
}

public DelegateCommand<object> AddUnicornCommand
{
get { return _AddUnicornCommand; }
}

public string FName
{
get { return _FirstName; }
set
{
if (_FirstName != value)
{
_FirstName = value;
RaisePropertyChanged(() => FName);
}
}
}

public string LName
{
get { return _LastName; }
set
{
if (_LastName != value)
{
_LastName = value;
RaisePropertyChanged(() => LName);
}
}
}

private void SidebarViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "FName":
case "LName":
AddUnicornCommand.RaiseCanExecuteChanged();
break;
}
}

private void AddUnicornExecute(object parameter)
{
Unicorn unicorn = new Unicorn() { FirstName = FName, LastName = LName };
_UnitOfWork.UnicornRepository.Insert(unicorn);
_UnitOfWork.Save();
}

#region IDataErrorInfo Members

public string Error
{
get
{
// no single error for the entire object
return null;
}
}

public string this[string columnName]
{
get
{
string errorMessage = null;
switch (columnName)
{
case "FName":
if (validateNameString(FName))
errorMessage = "Not valid this";
break;
case "LName":
if (validateNameString(LName))
errorMessage = "May not be empty";
break;
}

return errorMessage;
}
}

#endregion

// some basic input checks
private Func<string, bool> validateNameString = x => string.IsNullOrEmpty(x) || x.Length > 50;
}
}

Keep in mind that we save our object via the UnitOfWork and not directly via the UnicornRepository. IDataErrorInfo was also implemented.

It is time to add two Views to the Views folder. Start by adding a new User Control (WPF) called MainView.xaml to the project.

XAML code:

<UserControl x:Class="UnicornManager.Core.Views.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008">http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<TextBlock Text="Hello From MainView (Core Module)"
Grid.Row="0"/>
<ListBox ItemsSource="{Binding Unicorns, Mode=TwoWay}"
Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FirstName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</UserControl>

MainView codebehind:

namespace UnicornManager.Core.Views
{
/// <summary>
/// Interaction logic for MainView.xaml
/// </summary>
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class MainView : UserControl
{
public MainView()
{
InitializeComponent();
}

[Import]
public MainViewModel ViewModel
{
set { DataContext = value; }
}
}
}

Here we Export our view and we Import our ViewModel. Just some basic MEF importing and exporting.

Add another User Control (WPF) called SidebarView.xaml to the Views folder:

<UserControl x:Class="UnicornManager.Core.Views.SidebarView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008">http://schemas.microsoft.com/expression/blend/2008"
xmlns:prism="http://www.codeplex.com/prism">http://www.codeplex.com/prism"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<StackPanel>
<Label Content="First Name:" />
<TextBox Text="{Binding FName, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True}"/>
<Label Content="Last Name:" />
<TextBox Text="{Binding LName, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True}"/>

<Button Height="30"
Content="Add Unicorn"
Command="{Binding AddUnicornCommand}"/>
</StackPanel>
</Grid>
</UserControl>

Codebehind for the SidebarView:

namespace UnicornManager.Core.Views
{
/// <summary>
/// Interaction logic for SidebarView.xaml
/// </summary>
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class SidebarView : UserControl
{
public SidebarViews()
{
InitializeComponent();
}

[Import]
public SidebarViewModel ViewModel
{
set { DataContext = value; }
}
}
}

If we now run our application we still see the same empty window. This is because we forgot our Bootstrapper to tell that it can also search in our Module!

Select the UnicornManager project and add a reference to our Core project.
Next in the ConfigureAggregateCatalog method in our CoreBootstrapper add new AssemblyCatalogs for the Data and Core projects:

protected override void ConfigureAggregateCatalog()
{
base.ConfigureAggregateCatalog();
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(CoreBootstrapper).Assembly));
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Data.Models.Unicorn).Assembly));
this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(CoreModule).Assembly));
}

Now run the project and have fun! ;)

What I like to hear from you (and if possible with code examples or a link to the adjusted solution)

  • Is the structure for this project ok?
  • There is no need to configure a ModuleCatalog in the bootstrapper when working with Prism and MEF or is that not true?
  • The Entity Framework has also some validation of its Entities (see UnitOfWork class: DbEntityValidationException). Is there a way to work with DataAnnotations on the Entity Frame Model classes instead of implementing the IDataErrorInfo on the ViewModel. Because this feels like writing double code. How do you show Entity (validation) exceptions on the UI directly?
  • How would you implement a Ribbon + add and merge tabpages when having multiple Modules?
  • MVVM: Do the Models also require INotifyPropertyChanged or only the ViewModels?

Download the project source here. (It is UnicornManager.zip)

Links:

(Maybe somebody can extend the solution so that others (and myself!) can learn from it)

Visual Studio Editor about Visual Studio 2010 beta 2

Visual Studio Logo

Today the program manager, Brittany Behrens, from the Visual Studio Platform Team made a new blog post about Visual Studio 2010 beta 2.

The most important thing:

VS 2010 Beta2 sounds great. When can I get it?

More and more of you are asking when Beta2 will be released.  The release date hasn’t been announced, so we can’t say just yet.  But we certainly will post here when the date is public and again when Beta2 becomes available.

In the meantime, please do continue to use Beta1 and send us feedback through Connect bugs, forum posts, e-mail to the Editor team, and now Twitter.  Your input has helped us make huge improvements in VS 2010 since Beta1, and I hope you’ll continue to let us know what you think all the way through RTM.

Visual Studio 2010 beta 1 crashes

Visual Studio 2010 Beta 1 crashes Visual Studio 2010 beta 1 crashes

I really hope that the rumors about the Beta 2 release date in September 2009 are true! Because now it is really a PITA to see Visual Studio 2010 Beta 1 crashing all the time. :(

WPF Office Ribbon control

WPF Office Ribbon MSDN

A while ago Microsoft introduced the Ribbon control in various programs like Microsoft Word, Microsoft Excel, …
What if you are a WPF developer and you want to create a piece of software that uses such a Ribbon control? Where can I find it? How do I implement it? Is it free?
Many questions are still unanswered. I hope to answer some of the questions with this post, but a full detailed explanation can be found in the Resources section at the bottom of this post.

Where to find the WPF Office Ribbon control?

The Ribbon control is not a part of Visual Studio 2010 (speaking about beta 1 at this moment) nor .NET 4.0, even Expression Blend doesn’t give us that control. The Ribbon control can be found at the Office UI Licensing Developer Center . Click on ‘License the Office UI‘. In the next steps you will need to fill in a form to agree with the license. This is because you are using a Control from the Office team :).

Note: If you are creating a commercial application, don’t forget to mention the license, because you are using a Ribbon control with a signed license!

Now go ahead and download the WPF Ribbon control and the first step of getting the control is done for free!

ramones- hey ho let's go

Adding the WPF Ribbon control

  • with Visual Studio 2010 (similar to VS 2008)

Open Visual Studio 2010 and create a WPF Application called MyRibbonApp. The first thing that we need to do is adding a reference to our Ribbon control (the RibbonControlsLibrary.dll file that you have just downloaded).

Adding the Reference

  1. Right-mouse click on your project in the Solution Explorer.
  2. Select: Add Reference…
  3. Select tab page ‘Browse’ and browse until you find your RibbonControlsLibrary.dll that you downloaded.
  4. Click OK and the library should be listed under your References in the Solution Explorer.

Using it in XAML

This is the code that we now have:

<Window x:Class="MyRibbonApp.Window1"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 Title="Window1" Height="300" Width="300">
 <Grid>

 </Grid>
</Window>

Add the Reference to the namespaces so that we can access our Ribbon control.

<Window x:Class="MyRibbonApp.Window1"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
 Title="Window1"
 Height="600"
 Width="800">

Now we are ready to actually implement the Ribbon. First we need to change the Window tag to RibbonWindow:

<r:RibbonWindow x:Class="MyRibbonApp.Window1"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
 Title="Window1"
 Height="600"
 Width="800">
 <Grid>

</Grid>
</r:RibbonWindow>

If you try to run the application now you will have an error:

Partial declarations of ‘MyRibbonApp.Window1′ must not specify different base classes

Open your codebehind file (Window1.xaml.cs) and add a reference and change the Window.

...
using Microsoft.Windows.Controls.Ribbon;

namespace MyRibbonApp
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : RibbonWindow
{
public Window1()
{
...

See how we access the Ribbon control using the r: that we defined in the namespace. You can change that if you want to but I’ll work with ‘r‘ here.
The reason that we have to change the Window to RibbonWindow is very simple. If you see Word 2007 or any other application using the Ribbon, you will see that the ‘Quick access toolbar’ is implemented in the Windowborder itself.
A default Window tag doesn’t allow us to add things like the Quick access toolbar directly to the windowborder.

Ribbon in a normal Window tag

The Ribbon itself will be placed inside a DockPanel. So replace the Grid with a DockPanel, insert the Ribbon control inside the grid and always dock the ribbon to the top!

The code should now look like this:

<r:RibbonWindow  x:Class="MyRibbonApp.Window1"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
 Title="Window1"
 Height="600"
 Width="800">
 <DockPanel>
 <r:Ribbon DockPanel.Dock="Top" Title="teusje.wordpress.com">
 </r:Ribbon>
 </DockPanel>
</r:RibbonWindow>

Run your program (F5) and watch… you have your Ribbon!
Don’t worry if you see a black background, this is because we are using RibbonWindow. Just set an Background=”White” on the RibbonWindow and it will be fixed ;) .

Adding Tabs

The XAML code is very easy to understand. We just add 2 RibbonTabs inside our Ribbon:

<DockPanel>
 <r:Ribbon DockPanel.Dock="Top" Title="teusje.wordpress.com">
  <r:RibbonTab Label="Home" />
  <r:RibbonTab Label="Help" />
 </r:Ribbon>
</DockPanel>

Run your application (F5) and play around with your tabs (hover them, scroll with your mouse, etc..)

Ribbon RibbonTab

Adding content to the Tabs

In this step we will try to fill our tabs with some controls. Buttons and other controls are bundled together in a group called RibbonGroup. They hold controls that are similar. A group Clipboard could add Cut, Copy, Paste inside it, because they belong to each other. We will add these controls in our group using RibbonButton.

I’ll leave it up to you to discover different kind of buttons, most of them can be found by reading the official links and guidelines in the  Resources section at the bottom of this post.

The code for the Ribbon should look like this now:

<r:Ribbon DockPanel.Dock="Top" Title="teusje.wordpress.com">
 <!-- Home tab -->
 <r:RibbonTab Label="Home">
 <r:RibbonGroup Name="Clipboard">
 <r:RibbonButton />
 <r:RibbonButton />
 <r:RibbonButton />
 </r:RibbonGroup>
 </r:RibbonTab>
 <!-- Help tab -->
 <r:RibbonTab Label="Help" />
 </r:Ribbon>

Run your application by pressing F5 and move your mouse over the buttons. You will see a button highlight. :)

Ribbon RibbonGroup RibbonButton

Adding Commands

Now we are going to add Commands. RibbonCommands are designed to store the information like LabelTitles, ToolTips, Events, Images for the button… in one place. They can be reused or be moved to another file to keep your XAML code clean.

Change your 3 RibbonButtons to this code:

<r:RibbonGroup Name="Clipboard">
 <r:RibbonButton>
  <r:RibbonButton.Command>
   <r:RibbonCommand LabelTitle="Copy"
    ToolTipDescription="Copy something" />
  </r:RibbonButton.Command>
 </r:RibbonButton>
 <r:RibbonButton>
  <r:RibbonButton.Command>
   <r:RibbonCommand LabelTitle="Cut"
    ToolTipDescription="Cut something" />
  </r:RibbonButton.Command>
 </r:RibbonButton>
 <r:RibbonButton>
  <r:RibbonButton.Command>
   <r:RibbonCommand LabelTitle="Paste"
    ToolTipDescription="Paste something" />
  </r:RibbonButton.Command>
 </r:RibbonButton>
 </r:RibbonGroup>

Run your application now (F5). You will see that your buttons now have a name. If you want to add images  for your buttons you need to set the LargeImageSource and SmallImageSource attribute in your RibbonCommand. LargeImageSource needs images with an 48×48 size and SmallImageSource needs 16×16.
Have you noticed if you hover your buttons that they don’t have their highlight anymore? Don’t worry about this, this is we didn’t add ‘CanExecute’ and ‘Executed’ in our Command. We’ll do that later :).

Now imagine that you have 6 Tabs with on each tab around 15 buttons, your XAML code will become a big mess with all these RibbonCommands inside your menus! Also when you have a button in another tab that needs the same functionality as a button from another tab you need to copy/paste the same command. Duplicated code is not good we want to use our code again!

Using a ResourceDictionary for Commands

First of all we need to create a ResourceDictionary to store our commands. Create it just above your DockPanel, under the RibbonWindow opening tag:

<r:RibbonWindow  x:Class="MyRibbonApp.Window1"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
 Title="Window1"
 Height="600"
 Width="800"
 Background="White">

 <r:RibbonWindow.Resources>
  <ResourceDictionary>
   <r:RibbonCommand x:Key="CopyCommand"
    LabelTitle="Copy"
    ToolTipDescription="Copy something" />
   <r:RibbonCommand x:Key="CutCommand"
    LabelTitle="Cut"
    ToolTipDescription="Cut something" />
   <r:RibbonCommand x:Key="PasteCommand"
    LabelTitle="Paste"
    ToolTipDescription="Paste something" />
  </ResourceDictionary>
 </r:RibbonWindow.Resources>

 <DockPanel>

Now remove the commands from your buttons and replace them with Command attribute that has a  reference to your ResourceDictionary. I added also a Name attribute.

<r:RibbonGroup Name="Clipboard">
<r:RibbonButton Name="Copy"
Command="{StaticResource CopyCommand}" />
<r:RibbonButton Name="Cut"
Command="{StaticResource CutCommand}" />
<r:RibbonButton Name="Paste"
Command="{StaticResource PasteCommand}" />
 </r:RibbonGroup>

Now you see that our RibbonButtons don’t contain the design stuff anymore but only a command reference. Run your application, it should be the same as our previous version.

In your Window1.xaml.cs (the code behind file) add the following event handler:

private void OnIgnore(object sender, ExecutedRoutedEventArgs e)
 {
 // do nothing
 }

Now back to your Commands add the CanExecute parameter to each command and point it to OnIgnore:

<ResourceDictionary>
 <r:RibbonCommand x:Key="CopyCommand"
 LabelTitle="Copy"
 ToolTipDescription="Copy something"
 Executed="OnIgnore" />
 <r:RibbonCommand x:Key="CutCommand"
 LabelTitle="Cut"
 ToolTipDescription="Cut something"
 Executed="OnIgnore" />
 <r:RibbonCommand x:Key="PasteCommand"
   LabelTitle="Paste"
   ToolTipDescription="Paste something"
   Executed="OnIgnore" />
 </ResourceDictionary>

Run the application now (F5) and hover your buttons with your mouse. You see, they are fine now ;).

Ribbon RibbonButton mouse hover

Now go and add images to your buttons. (I will not do this you if you have time to do this, have fun :P ) As said before you should add in each Command a LargeImageSource and SmallImageSource. It can look like this:

<r:RibbonCommand x:Key="CopyCommand"
 LabelTitle="Copy"
 ToolTipDescription="Copy something"
 Executed="OnIgnore"
 LargeImageSource="Images/copyIcon48x48.png"
 SmallImageSource="Images/copyIcon16x16.png" />

You have seen that I used Executed in the Command. You can implement other events also like CanExecute. I point everything in this little tutorial  just to one event handler called OnIgnore, but normally you will have different events for each button.

Using GroupSizeDefinitions

Ever noticed when you open your Word 2007, when you resize Word that the RibbonButtons become bigger or smaller? Well this can be done with GroupSizeDefinitions.

Create this resource container inside your Ribbon tag, just like this:

...
<DockPanel>
 <r:Ribbon DockPanel.Dock="Top" Title="teusje.wordpress.com">
  <r:Ribbon.Resources>
   <r:RibbonGroupSizeDefinitionCollection x:Key="RibbonLayout">
    <r:RibbonGroupSizeDefinition>
     <!-- Control sizes: L,L,L -->
     <r:RibbonControlSizeDefinition ImageSize="Large" IsLabelVisible="True" />
     <r:RibbonControlSizeDefinition ImageSize="Large" IsLabelVisible="True" />
     <r:RibbonControlSizeDefinition ImageSize="Large" IsLabelVisible="True" />
    </r:RibbonGroupSizeDefinition>
    <r:RibbonGroupSizeDefinition>
     <!-- Control sizes: L,M,M -->
     <r:RibbonControlSizeDefinition ImageSize="Large" IsLabelVisible="True" />
     <r:RibbonControlSizeDefinition ImageSize="Small" IsLabelVisible="True" />
     <r:RibbonControlSizeDefinition ImageSize="Small" IsLabelVisible="True" />
    </r:RibbonGroupSizeDefinition>
    <r:RibbonGroupSizeDefinition>
     <!-- Control sizes: L,S,S -->
     <r:RibbonControlSizeDefinition ImageSize="Large" IsLabelVisible="True" />
     <r:RibbonControlSizeDefinition ImageSize="Small" IsLabelVisible="False" />
     <r:RibbonControlSizeDefinition ImageSize="Small" IsLabelVisible="False" />
    </r:RibbonGroupSizeDefinition>
    <!-- Collapsed -->
    <r:RibbonGroupSizeDefinition IsCollapsed="True" />
   </r:RibbonGroupSizeDefinitionCollection>
  </r:Ribbon.Resources>

 <!-- Home tab -->
...

Now add a GroupSizeDefinition to your groups. This GroupSizeDefinition called RibbonLayout is made for 3 buttons in a group. If you have groups with more buttons and you want to define how they should resize you can make another GroupSizeDefinition called OtherRibbonLayout for example.

<!-- Home tab -->
 <r:RibbonTab Label="Home">
 <r:RibbonGroup Name="Clipboard"
 GroupSizeDefinitions="{StaticResource RibbonLayout}">

This image from WindowsClient.net shows the effect/result (they used a definition for 4 buttons here):

Ribbon resize image from windowsclient.net

Implementing the RibbonQuickAccessToolBar (QAT)

Add this under your Ribbon.Resources tag:

<r:Ribbon.QuickAccessToolBar>
 <r:RibbonQuickAccessToolBar CanUserCustomize="True">
  <r:RibbonButton Command="{StaticResource CopyCommand}" r:RibbonQuickAccessToolBar.Placement="InCustomizeMenuAndToolBar" />
  <r:RibbonButton Command="{StaticResource CopyCommand}" r:RibbonQuickAccessToolBar.Placement="InCustomizeMenuAndToolBar" />
  <r:RibbonButton Command="{StaticResource CopyCommand}" r:RibbonQuickAccessToolBar.Placement="InCustomizeMenuAndToolBar" />
  <r:RibbonButton Command="{StaticResource PasteCommand}" r:RibbonQuickAccessToolBar.Placement="InToolBar" />
 </r:RibbonQuickAccessToolBar>
 </r:Ribbon.QuickAccessToolBar>

Your QAT will now look like this:

Ribbon QuickAccessToolbar QAT

If you hover your mouse over the left side of the Window you will see that your 4 little buttons will highlight.

Ribbon QAT buttons in toolbar

It’s just because I didn’t implement the LargeImageSource and SmallImageSource that you don’t see an Icon for the button. ;)

Also watch the details, in the dropdown you have 3 items and in the Toolbar above you have 4 buttons.We did this with:

r:RibbonQuickAccessToolBar.Placement="InCustomizeMenuAndToolBar"
and

r:RibbonQuickAccessToolBar.Placement="InToolBar"

Creating an ApplicationMenu

Add the ApplicationMenu between your ribbon resources and your QuickAccessToolbar like this:

...
</r:Ribbon.Resources>

 <r:Ribbon.ApplicationMenu>
 <r:RibbonApplicationMenu>
 <r:RibbonApplicationMenu.Command>
 <r:RibbonCommand
 Executed="OnIgnore"
 LabelTitle="Application Button"
 LabelDescription="Close the application."
 ToolTipTitle="MyRibbonApp"
 ToolTipDescription="Click here to use my menu."
 ToolTipFooterTitle="Help"
 ToolTipFooterDescription="Press F1 for more help." />
 </r:RibbonApplicationMenu.Command>
 <r:RibbonApplicationMenuItem Command="{StaticResource CopyCommand}" />
 <r:RibbonApplicationMenuItem Command="{StaticResource CopyCommand}" />
 <r:RibbonApplicationMenuItem Command="{StaticResource CutCommand}" />
 <r:RibbonApplicationMenuItem Command="{StaticResource CopyCommand}" />
 <r:RibbonApplicationMenuItem Command="{StaticResource CopyCommand}" />
 <r:RibbonSeparator />
 <r:RibbonApplicationMenuItem Command="{StaticResource PasteCommand}" />
 <r:RibbonApplicationMenu.Footer>
 <DockPanel LastChildFill="False">
 <r:RibbonButton DockPanel.Dock="Right"
 Margin="2"
 Command="{StaticResource CopyCommand}" />
 <r:RibbonButton DockPanel.Dock="Right"
 Margin="2"
 Command="{StaticResource PasteCommand}" />
 </DockPanel>
 </r:RibbonApplicationMenu.Footer>
 </r:RibbonApplicationMenu>
 </r:Ribbon.ApplicationMenu>

 <r:Ribbon.QuickAccessToolBar>
...

You see that we implemented a Command inside the ApplicationMenu itself. We did this because we will only need this command there, no other control will ever need it so sometimes not everything has to be in your resources.

If you hover your ApplicationMenu you will see a nice ToolTip:

Ribbon ApplicationMenu Tooltip

If you want to style the ApplicationMenuTooltip a bit more you can use ToolTipFooterImageSource, SmallImageSource, etc... just explore it yourself ;)

If you click your menu you will see something like this:

Ribbon ApplicationMenu

Adding Office 2007 Style

Add this code in your RibbonWindow Resources:

<r:RibbonWindow.Resources>
 <ResourceDictionary>
 <ResourceDictionary.MergedDictionaries>
 <ResourceDictionary Source="/RibbonControlsLibrary;component/Themes/Office2007Blue.xaml" />
 </ResourceDictionary.MergedDictionaries>

Your Ribbon will now have the Office 2007 Blue styles:

Ribbon Office2007 Blue Style

Office 2007 Blue style:

 <ResourceDictionary Source="/RibbonControlsLibrary;component/Themes/Office2007Blue.xaml" />

Office 2007 Black style:

 <ResourceDictionary Source="/RibbonControlsLibrary;component/Themes/Office2007Black.xaml" />

Office 2007 Silver style:

 <ResourceDictionary Source="/RibbonControlsLibrary;component/Themes/Office2007Silver.xaml" />

You

Well now YOU have to create a Command for every button or thing that you want in your Ribbon control. You can add icons/images for the buttons with LargeImageSource and SmallImageSource inside your Command.

Check out the Resource links, they have more information on how to build your Ribbon control and they explain several buttons.

Resources

Source Code download:

MyRibbonApp

MyRibbonApp (Hope this one works)

RENAME .doc TO .zip !!! (wordpress doesn't allow me to upload .zip files).


I hope you liked this little Ribbon tutorial. :)

Simple Binding in WPF with XAML

For the absolute beginners that don’t know what binding is we will create a little application that takes only 1 minute of your time. We will use a Slider and a TextBlock and place them inside a StackPanel.
Very basic things, no rocket science.

Our goal is to increase or decrease the font size from the TextBlock by moving our Slider left and right.

Here we go:

Open Visual Studio 2008 or Visual Studio 2010 and create a new WPF Application called ‘SimpleBinding‘.

Your Windows1.xaml will look like the code below. We will not use our codebehind (Window1.xaml.cs) file.

<Window x:Class="SimpleBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Grid>

    </Grid>
</Window>

In our next step we replace the Grid with a StackPanel and add 2 StackPanel childs: TextBlock and Slider.

 <Window x:Class="SimpleBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <Slider />
        <TextBlock />
    </StackPanel>
 </Window>
 

Our final step is to bind the TextBlock to the Slider. Therefore we will use a MarkupExtension, you can recognize it by the braces { and }.

<Window x:Class="SimpleBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     Title="Window1" Height="300" Width="300">
     <StackPanel>
        <Slider x:Name="mySlider"
                Minimum="10"
                Maximum="72" />
        <TextBlock Text="This is simple binding!"
                   HorizontalAlignment="Center"
                   FontSize="{Binding ElementName=mySlider, Path=Value}" />
    </StackPanel>
</Window>

Press F5 and test your little WPF application now and see how it works.

We have given our Slider a name ‘mySlider‘ with x:Name=”” attribute so that we can use in our TextBlock.
The Binding itself is very easy. The word Binding tells us that ‘We are going to bind something’, ElementName is used to say ‘What control do we want to bind?’ and the Path tells us ‘What will we use from our ElementName?‘ .

So that’s it, a very simple but powerful binding using only XAML and no C# code in our codebehind file.