MEF for Beginner – Part 3 (Hello Silverlight)

2009/12/19

one comment

MEF for Beginner – Part 3 (Hello Silverlight)

in this post we will cover the basic steps that is needed for building your first Silverlight MEF application.

you can find more about the MEF on part 1, part 2 of this series, the series TOC is available here.

the following instructions will lead you through very simple steps of building simple Silverlight shell application

that can consume plug-ins.

this post is written on Visual Studio 2010 and Silverlight 4.0 (using Visual studio 2008 and Silverlight 3

will need some minor modification and download the MEF Silverlight 3 bits from the MEF site).

 

in the next post on this series, we will extend the current post by learning how to consume external plug-ins using a-sync loading .

 

the code sample for this post can be download from here.

 

Step 1: Creating Silverlight Application

Create solution using the Silverlight application template.

MEF, IoC, Silverlight 4, Extesibility

 

Step 2: Setting the Shell layout

the layout of the shell will have 2 area (plug-in command area and main area):

the plug-ins commands will host in StackPanel control

and the main content area will have a Border and TextBlock controls within a Canvas.

add the following Xaml into the Grid element of the main page.

Code Snippet
  1. <Grid.ColumnDefinitions>
  2.     <ColumnDefinition Width="150" />
  3.     <ColumnDefinition Width="308*" />
  4. </Grid.ColumnDefinitions>
  5. <StackPanel Orientation="Vertical" Grid.Column="0">
  6. </StackPanel>
  7. <Canvas x:Name="_mainContentPlaceHolder" Grid.Column="1" >
  8.     <Border x:Name="_mainBorder" Width="250" Height="100" BorderThickness="1" CornerRadius="1" Margin="4">
  9.         <TextBlock x:Name="_mainText" Text="Some content"/>
  10.     </Border>
  11. </Canvas>

 

Step 3: Binding the StackPanel to plug-ins list

add the ItemControl element into the StackPanel (see it’s binding definition)

Code Snippet
  1. <StackPanel Orientation="Vertical" Grid.Column="0">
  2.     <ItemsControl ItemsSource="{Binding Path=ToolbarItems}" />
  3. </StackPanel>

 

add ObservableCollection of UserControl property called ToolbarItems into the Shell code behind
(the binding definition at the Xaml level refer to this property)

Code Snippet
  1. public ObservableCollection<UserControl> ToolbarItems { get; set; }

 

initialize the ToolbarItems property and the Context at the constructor,

(the following lines should be add to the constructor).

Code Snippet
  1. ToolbarItems = new ObservableCollection<UserControl>();
  2. DataContext = this;

 

Step 4: add reference to MEF

before adding the plug-able functionality, we have to add reference to MEF.

add new reference and browse for System.ComponentModel.Composition.dll under the following folder:

64 bit: C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Libraries\Client

32 bit: C:\Program Files\Microsoft SDKs\Silverlight\v4.0\Libraries\Client

MEF, IoC, Silverlight 4, Extesibility

 

Step 5: decorate the ToolbarItems property

decorating the ToolbarItems property with ImportMany attribute, will shift the responsibility of

filling it with UserControl instances to MEF (which is basically saying to MEF

that it should add any item that was Export and match the contract (in our case UserControl).

the ToolbarItems should now look like this:

Code Snippet
  1. [ImportMany]
  2. public ObservableCollection<UserControl> ToolbarItems { get; set; }

 

Step 6: expose the Element within the main area

the shell will expose the Border and the TextBlock within it main area so it can be

discoverable by the plug-ins.

to achieve this task we will add 2 properties (at the code behind) and decorate it with Export attribute.

Code Snippet
  1. [Export]
  2. public TextBlock MainText
  3. {
  4.     get { return _mainText; }
  5. }
  6.  
  7. [Export]
  8. public Border MainBorder
  9. {
  10.     get { return _mainBorder; }
  11. }

 

Step 7: Create exportable entities (create plug-ins)

Note: on this post we will add the plug-ins within the same package as our Shell,

          but in the next post in this series we will show how to discover exportable

          parts within external packages. 

Create Parts folder in the project and add Silverlight User Control (PlugableEffect1.xaml)

MEF, IoC, Silverlight 4, Extesibility

 

Step 7.1: Stet the look and feel of the effect command

add the following Xaml into the Grid element (of the effect xaml)

Code Snippet
  1. <Button Command="{Binding}" Width="Auto" Height="Auto">
  2.     <TextBlock Text="Effect 1"/>
  3. </Button>

 

Step 7.2: Add TextBlock property that present the TextBlock at the Shell main area

also this plug-in is capable of manipulate a TextBlock, it shouldn’t be aware of

the TextBlock origin.

to achieve the above requirements we will once again add decorated property,

which will be assigned by MEF at runtime.

this time we expecting single value, therefore we will decorate the property with the Import attribute

rather the ImportMany attribute.

Note: MEF will find the exported TextBlock which we expose at step 6 and assign it into the following property.

Code Snippet
  1. [Import]
  2. public TextBlock ShellText { get; set; }

 

Step 7.3: Set the effect command

looking at the Xaml of the button we can see that it use the Command="Binding"

this mean that the button expect ICommand implementation within it’s data context.

at the code behind of this effect, add the following line to the constructor.

Code Snippet
  1. DataContext = this;

 

and implement ICommand

Code Snippet
  1. public partial class PlagableEffect1 : UserControl, ICommand

Code Snippet
  1. public bool CanExecute(object parameter)
  2. {
  3.     return true;
  4. }
  5.  
  6. public event EventHandler CanExecuteChanged;
  7.  
  8. public void Execute(object parameter)
  9. {
  10.     ShellText.Text = "Effect 1";
  11.     ShellText.FontSize = 32.0;
  12.     ShellText.Foreground = new SolidColorBrush(Colors.Red);
  13.     ShellText.FontFamily = new FontFamily("Comic Sans MS");
  14. }

 
Step 7.4: Export our effect

making the effect visible to MEF done by decorating the class with Export attribute.

Code Snippet
  1. [Export(typeof(UserControl))]
  2. public partial class PlugableEffect1 : UserControl, ICommand

 

Step 8: Create another exportable entities (create plug-ins)

repeat step 7 for Effect 2 (replace the Effect 1 text to Effect 2).

then add another property decorated with Import for the shell Border element.

Code Snippet
  1. [Import]
  2. public Border ShellBorder { get; set; }

 

replace the Execute method implementation of the Effect 2 command to the following:

Code Snippet
  1. public void Execute(object parameter)
  2. {
  3.     ShellText.Text = "Effect 2";
  4.     ShellText.FontSize = 24.0;
  5.     ShellText.Foreground = new SolidColorBrush(Color.FromArgb(255, 33, 33, 33));
  6.     ShellText.FontFamily = new FontFamily("Comic Sans MS");
  7.     ShellText.FontWeight = FontWeights.ExtraBold;
  8.     ShellText.VerticalAlignment = System.Windows.VerticalAlignment.Center;
  9.     ShellText.HorizontalAlignment = HorizontalAlignment.Center;
  10.  
  11.     ShellBorder.BorderThickness = new Thickness(8);
  12.     ShellBorder.BorderBrush = new SolidColorBrush(Colors.Gray);
  13.     ShellBorder.CornerRadius = new CornerRadius(10.0);
  14.     ShellBorder.Background = new SolidColorBrush(Colors.Orange);
  15.     ShellBorder.Width = 250;
  16.     var rt = new RotateTransform();
  17.     rt.Angle = 45;
  18.     rt.CenterX = 1.5;
  19.     rt.CenterY = 30;
  20.     ShellBorder.RenderTransform = rt;
  21. }

 

Step 9: Compose it all together

before we continue we have to add reference to System.ComponentModel.Composition.Packaging.Toolkit.dll

this dll is part of the MEF Silverlight Toolkit

image

after installing the toolkit you can find the System.ComponentModel.Composition.Packaging.Toolkit.dll

at C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Toolkit\Nov09\Bin (for 64 bit)

and at C:\Program Files\Microsoft SDKs\Silverlight\v4.0\Toolkit\Nov09\Bin (for 32 bit)

 

Step 9.1: Compose

the last step involve is asking MEF to compose.

we will supply MEF with some basics instruction and ask it to assign all the Import with

Export that matches the Import’s needs.

Add the following method to the App.xaml code behind.

Code Snippet
  1. private void InitializeContainer(UIElement mainWin)
  2. {
  3.     var catalogs = new PackageCatalog();
  4.     catalogs.AddPackage(Package.Current);
  5.     var mainWinPart = AttributedModelServices.CreatePart(mainWin);
  6.     var batch = new CompositionBatch(new[] { mainWinPart }, null);
  7.     var container = new CompositionContainer(catalogs);
  8.     container.Compose(batch);
  9. }

the above code create a Catalog (at lines 3,4) ,

Catalog used as instruction for where to search for the compose-able parts.

in this case we instruct MEF to look for compose-able parts within the current Silverlight package.

at lines 5,6 we add the current instance of the Shell into CompositionBatch, this will instruct the MEF container

to use this instance rather of creating new one.

line 7, 8 add the Catalog and the CompositionBatch to a CompositionContainer and perform the composition.

 

the last peace of code is calling the above method from the application startup.

Code Snippet
  1. private void Application_Startup(object sender, StartupEventArgs e)
  2. {
  3.     this.RootVisual = new MainPage();
  4.     InitializeContainer(this.RootVisual);
  5. }

 

Summary

this post had demonstrate how to build compose-able shell using Silverlight 4.0.

in the next post we will continue to enhance the sample by adding a-sync loading capability

to external Silverlight packages that holding compose-able parts (Plug-ins).

 

Downloads

the code sample for this post can be download from here.

you will need Silverlight 4 and the Silverlight 4 toolkit. You can download Silverlight 4 beta  here and the toolkit here.

 

Learn More

you can find more information on how to use MEF over Silverlight in the following posts (by Glenn Block):

Building the Hello MEF dashboard in Silverlight 4 – Part I 

Building Hello MEF – Part II – Metadata and why being Lazy is a good thing.

Building Hello MEF – Part III – XAP Partitioning (with the host’s permission) and the sweetness of recomposition.

 

Updates

the MEF API for Silverlight Catalog has changed,

instead using the PackageCatalog you should now use the DeploymentCatalog.

other changes were:

PartIntializer renamed to CompositionInitializer (Silverlight only)

and PartCreator renamed to ExportFactory<T> and moved to System.ComponentModel.Composition.Initialization assembly (Silverlight only)


Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

one comment

  1. ganar online2010/02/04 ב 20:20

    Great idea, thanks for this tip!

    Reply