XAML Playground
about XAML and other Amenities

Inject ApplicationServices with MEF reloaded: supporting recomposition

2011-02-17T16:35:03+01:00 by Andrea Boschin

In my I've presented a simple solution that allows people to adds instances of ApplicationServices, without the need of adding the markup to the App.xaml file. The solution was interesting as a demonstration of how MEF works, but after some tests and some feedbacks I had I realized it is not applicable in a real world solution because of a subtle problem.

The problem is given by a conflict in the lifetime of the application between the Application_Start event and the StartService method. If you put the code to inizialize the CompositionContainer inside of the Application_Start event you may get an error stating that the composition has already initialized, just because when the StartService method call the CompositionInitializer method, to compose the services, the container is implicitly initialized. Unfortunately the Application_Start method is called after the StartService so here is the reason of the error you get.

For a long while I've thinked this may remain only a beautiful example because I do not discovered a valid solution, but today I convinced myself that a correction to this problem is possible and that it also add the ability of supporting recomposition to the HostService. As far as I know there is not any concern in calling the methods of the service with a delay respect the runtime raises the corrisponding method, almost until the method is not one of the Exit flavour. During the exit we have to free resources, stop threads, and so on and it is important to make these actions as soon as possible to let the runtime able to close the application faster. But the initialization phase may start in a later time, with the sole constraint that the sequence of the methods should be the same.

So this morning I've worked in this direction and in the following box you can see the resulting solution:

   1: public class HostService : IApplicationService, IApplicationLifetimeAware, IPartImportsSatisfiedNotification
   2: {
   3:     /// <summary>
   4:     /// Gets or sets the context.
   5:     /// </summary>
   6:     /// <value>The context.</value>
   7:     public ApplicationServiceContext Context { get; set; }
   8:     /// <summary>
   9:     /// Gets or sets the current.
  10:     /// </summary>
  11:     /// <value>The current.</value>
  12:     public static HostService Current { get; private set; }
  13:  
  14:     /// <summary>
  15:     /// Gets or sets the initialized.
  16:     /// </summary>
  17:     /// <value>The initialized.</value>
  18:     private List<IApplicationService> Initialized { get; set; }
  19:  
  20:     /// <summary>
  21:     /// Gets or sets the services.
  22:     /// </summary>
  23:     /// <value>The services.</value>
  24:     [ImportMany(AllowRecomposition = true, RequiredCreationPolicy = CreationPolicy.Shared)]
  25:     public List<IApplicationService> Services { get; set; }
  26:  
  27:     /// <summary>
  28:     /// Initializes a new instance of the <see cref="HostService"/> class.
  29:     /// </summary>
  30:     public HostService()
  31:     {
  32:         if (HostService.Current != null)
  33:             throw new InvalidOperationException("Service already exists");
  34:  
  35:         HostService.Current = this;
  36:         this.Initialized = new List<IApplicationService>();
  37:     }
  38:  
  39:     /// <summary>
  40:     /// Called by an application immediately after the <see cref="E:System.Windows.Application.Exit"/> event occurs.
  41:     /// </summary>
  42:     public void Exited()
  43:     {
  44:         foreach (IApplicationLifetimeAware service in this.Services.OfType<IApplicationLifetimeAware>())
  45:             service.Exited();
  46:     }
  47:  
  48:     /// <summary>
  49:     /// Called by an application immediately before the <see cref="E:System.Windows.Application.Exit"/> event occurs.
  50:     /// </summary>
  51:     public void Exiting()
  52:     {
  53:         foreach (IApplicationLifetimeAware service in this.Services.OfType<IApplicationLifetimeAware>())
  54:             service.Exiting();
  55:     }
  56:  
  57:     /// <summary>
  58:     /// Called by an application immediately after the <see cref="E:System.Windows.Application.Startup"/> event occurs.
  59:     /// </summary>
  60:     public void Started()
  61:     {
  62:         CompositionInitializer.SatisfyImports(this);
  63:     }
  64:  
  65:     /// <summary>
  66:     /// Called by an application immediately before the <see cref="E:System.Windows.Application.Startup"/> event occurs.
  67:     /// </summary>
  68:     public void Starting()
  69:     {
  70:     }
  71:  
  72:     /// <summary>
  73:     /// Called by an application in order to initialize the application extension service.
  74:     /// </summary>
  75:     /// <param name="context">Provides information about the application state.</param>
  76:     public void StartService(ApplicationServiceContext context)
  77:     {
  78:         this.Context = context;
  79:     }
  80:  
  81:     /// <summary>
  82:     /// Called by an application in order to stop the application extension service.
  83:     /// </summary>
  84:     public void StopService()
  85:     {
  86:         foreach (IApplicationService service in this.Services)
  87:             service.StopService();
  88:     }
  89:  
  90:     /// <summary>
  91:     /// Called when a part's imports have been satisfied and it is safe to use.
  92:     /// </summary>
  93:     public void OnImportsSatisfied()
  94:     {
  95:         // buffer for services that raises exception during initialization
  96:         List<IApplicationService> errors = new List<IApplicationService>();
  97:  
  98:         // call StartService
  99:         foreach (IApplicationService service in this.Services.OfType<IApplicationService>().Except(this.Initialized))
 100:         {
 101:             try
 102:             {
 103:                 service.StartService(this.Context);
 104:             }
 105:             catch
 106:             {
 107:                 errors.Add(service);
 108:             }
 109:         }
 110:  
 111:         // call Starting
 112:         foreach (IApplicationLifetimeAware service in 
 113:             this.Services.OfType<IApplicationLifetimeAware>()
 114:             .Except(this.Initialized.OfType<IApplicationLifetimeAware>())
 115:             .Except(errors.OfType<IApplicationLifetimeAware>()))
 116:         {
 117:             try
 118:             {
 119:                 service.Starting();
 120:             }
 121:             catch
 122:             {
 123:                 errors.Add((IApplicationService)service);
 124:             }
 125:         }
 126:  
 127:         // call Started
 128:         foreach (IApplicationLifetimeAware service in 
 129:             this.Services.OfType<IApplicationLifetimeAware>()
 130:             .Except(this.Initialized.OfType<IApplicationLifetimeAware>())
 131:             .Except(errors.OfType<IApplicationLifetimeAware>()))
 132:         {
 133:             try
 134:             {
 135:                 service.Started();
 136:             }
 137:             catch
 138:             {
 139:                 errors.Add((IApplicationService)service);
 140:             }
 141:         }
 142:  
 143:         // register ad Initialized to avoid duplicated initialization in case of recomposition
 144:         foreach (IApplicationService service in 
 145:             this.Services.OfType<IApplicationService>()
 146:             .Except(this.Initialized)
 147:             .Except(errors))
 148:             this.Initialized.Add(service);
 149:  
 150:         // remove services that raised exceptions
 151:         foreach (IApplicationService service in errors)
 152:             this.Services.Remove(service);
 153:     }
 154: }

As you can see the structure of the service remains the same, and also the management of the Exit, Exited and StopService is not changed. The very important change is in the Started method, that is called after the Application_Start event. In this method I only perform the composition. Then, in the OnImportsSatisfied method I start a sequence to emulate the startup of the service, repeating the flow that an ApplicationService usually follow during it initialization. I've also added some code to manage exceptions raised during the initialization. In these cases the services that raised the errors do not follow the remaining parts of the initialization and finally are removed from the Services collection.

In the service I maintain a collection of Initialized services because if the recomposition happen I must not repeat the inizialization of services that were already initialized previously. This is also the reason that make me asking a Shared CreationPolicy, because when the composition container compose the Services property does not have to create new instances but only have to add the new services coming from the recomposition.

I hope this solution to be more reliable than the previous one. As usual I will be glad to have feedback from you to continue improving the code..

Categories:   TIPS
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Singleton ApplicationServices explained

2011-02-17T09:44:39+01:00 by Andrea Boschin

My has opened to some unexpected questions about what may seems a strangeness in my code. I was surprised about this questions, just because I believed it was a known pattern, so I decided to give an explanation to ones that does not know the reason I wrote some lines of code in the constructor

   1: public class SampleService : IApplicationService
   2: {
   3:     public static SampleService Current { get; private set; }
   4:  
   5:     /// <summary>
   6:     /// Initializes a new instance of the <see cref="ServiceHost"/> class.
   7:     /// </summary>
   8:     public SampleService()
   9:     {
  10:         if (SampleService.Current != null)
  11:             throw new InvalidOperationException("Service already exists");
  12:  
  13:         SampleService.Current = this;
  14:     }
  15:  
  16:     // omissis...
  17: }

The problem here is that sometimes it is not useful (and sometimes it is definitely bad) to have more than an instance of an ApplicationService running behind the scenes. Given that none can limit the number of instances in the ApplicationLifetimeObjects collection I use a pattern to avoid this problem.

First of all I expose a static property "Current". This property is useful to interact with the running service from any part of the code. Since after the beta there is not an indexer to access the running service this is the most common pattern used for this purpose.

Then in the constructor I check the property "Current" to be null. If I found a value it means someone is trying to put two instances of the service in the markup, so I raise an exception stating that only one instance is allowed. In the case "Current" is empty I save myself to this property using "this".

So nothing is wrong in my previous example. Only few lines of code to implement a Singleton pattern for IApplicationService, with a tecnique that is widely used also inside the framework classes.

Categories:   TIPS
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Windows Phone 7 series continues...

2011-02-02T16:46:26+01:00 by Andrea Boschin

SilverlightShowAbout two weeks ago I started a series of articles about the Windows Phone 7 hosted by the well knows site SilverlightShow. In the very first rows of the opening article I wrote: "Starting with this article we will follow a path to discover one by one all the aspects of this device". The intent of the series is infact to give a walkthrough, starting from scratch, about the brand new device that is born in the previous months.

Now we are at the third number of the series and after having explained the most simple but not always obvious details of the UI, now it is time to go forward to explore the navigation paradigm that permeates you phone. This number will introduce to the problems of application lyfecycle and tombstoning that will be the argument of the fourth part I'm about to write.

If you have lost the previous number here is the links:

Windows Phone 7 Part #1: Getting Started

Windows Phone 7 Part #2: Your first app

As usual, if you have feedback or requests, you have only to write me or to Silverlightshow and we will fast answer to your needs.

Have a good reading

Categories:   News
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Remove Transformation from shapes in Blend

2011-01-24T13:49:54+01:00 by Andrea Boschin

Recently I'm working hard with Expression Blend to create some interfaces starting from some Illustrator mockups, made by a designer and also creating the user interface of some Windows Phone 7 applications I developed. One thing I've found annoying is that once you create a shape and you rotate it in the designer, Blend uses a CompositeTransform to render the shape in the XAML markup. If you are creating lot of elements (in my case they were the ticks of a gauge) you can get lot of transformations that the plugin or the phone have to render. And to me (particularly from my developer side), this is no a good thing since many times a rotated rectangle might be represented as a Path instead of using the CompositeTransform.

After realizing that creating the shape by hand is not an option I searched hard the options in the menu items because in my mind it was obvious to have a "Make transform static" option. But it simply does not exists (or at least I was unable to find it). So for a long time I decided to close my eyes and accept the Transformations. This until I found a tricky way to convince Blend to perform this operation as a side effect of a sequence of common operations. Here is the process I found:

First of all create the Shape. In this example I will use a Rectangle:

Capture1

Then I apply the Transformation I need. For this example I simply rotate the shape with the mouse of an amout of degrees:

Capture2

Now select the shape and find the option in the context menu (or in the Objects Tree) to make the shape a Path (Path -> Convert To Path). Obviously, to remove the transformation, you have to make the rectangle a Path. Once you have done this you will have this in the Object tree:

Capture3

As now Blend have performed the conversion but the CompositeTrasform is still in place. To convince Blend we have another couple of steps. Now Draw another shape (a rectangle) over the shape to convert. See in figure the result:

Capture4

Then Convert also this Rectangle to a Path. After this step the Objects Tree will show two paths one on top of the other. In the figure I've named the upper Shape to "Mask":

Capture5

Finally, and it is the tricky thing you have to deselect both the Paths (e.g. selecting the LayoutRoot element) then select again them starting from "Mask" then (using CTRL) the shape to convert. It is important to be aware that in the conversion the order matter. If you select the shapes in the inverse order you will not reach the required result. Then finally from the context menu select Combine -> Intersect. The resulting shape is this:

Capture6

The type of selection makes evident that now the Shape ha no rotation but we can see at the markup and the result is reported here:

   1: <Grid x:Name="LayoutRoot" Background="White">
   2:     <Path x:Name="Mask" 
   3:         Data="M29.362633,1.5 L101.14476,29.362633 L73.282127,101.14476 L1.5,73.282127 z" 
   4:         Fill="#FFFFD200" 
   5:         Margin="228.678,148.678,308.678,228.678" 
   6:         Stretch="Fill" Stroke="Black" StrokeThickness="3" UseLayoutRounding="False"/>
   7: </Grid>

Now you are ready to put the shape wherever you need it. I've experimented the trick in many ways and until today I never found a case where it does not works. The sole things you have to keep in mind is the right order of the steps, and that you can convert only a single shape at a time. So for my Gauge I had to make the conversion many times.

As a suggestion I think it would be beautiful to have an additional menu item that does the trick automatically... If someone knows a better way please feel free to write me and I will be very grateful.

Technorati Tags: ,,
Categories:   TIPS
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

New series of articles about WP7

2011-01-19T23:28:43+01:00 by Andrea Boschin

After a huge timeframe I return to my writing activity starting a series of articles about Windows Phone 7 for SilverlightShow website. During this time I've find the time to develop many samples for this device to prepare some speeches and I've created two applications for the marketplace.

The intent of the new series is to collect a number of articles, starting from scratch up to the very complicated subjects and I've started today with the very first and basic article about how to get started. In this article explain the architecture of the phone, and how to startup the development environment to be ready to write your own applications and deploy to the marketplace. Here is the planned table of contents of the series, but keep in mind that if you believe I miss something you can let me know and I manage to extend the series:

(19/1/2011)
 
Windows Phone 7 Part #2: Your first app
 
Windows Phone 7 Part #3: Understanding navigation
 
Windows Phone 7 Part #4: The application lifecycle
 
Windows Phone 7 Part #5: Panorama and Pivot controls
 
Windows Phone 7 Part #6: Advanced interaction
 
Windows Phone 7 Part #7: Understanding Push Notifications
 
Windows Phone 7 Part #8: Using Sensors

As you can see the road is long, since many arguments are covered by the series. I hope you will enjoy reading them but as I've already said if you think there is something to change contact me or the SilverlightShow website and we evaluate your proposals.

Simplify localization with a T4 template

2010-11-25T23:07:04+01:00 by Andrea Boschin

If you evere tryied to localize a Silverlight application, you have found for sure that it is not a straighforward task. Like all the other .NET tecnologies the Silverlight projects has resource files and you can create satellite assemblies to contains culture specific strings. But the problem is that it is not so easy to bring this string to the interface.

When you create a resx file Visual Studio generates a code file with a class ready to be used to read the strings. You can also choose to make this class public, so it is possible to use it across different projects. Unfortunately this class has an internal constructon so there is no way to add an instance to the App.xaml resources and use DataBinding to reference the strings in the user interface.

Someone suggest to manually change the ctor of the class but to me it is very frustrating to correct this simple bug every time I add a new resource. So it is required to create a proxy class, that wraps the static one. Every property will call the correspondent static property and then the proxy class will be used for the DataBinding. When you are developing a simple application this is a simple task, but what about when you have an huge number of strings?

With this in mind I've worked to a T4 template that it is able to read a resx file and automatically produces the proxy class. If you do not know it, the T4 template is a very powerful tool that exists since Visual Studio 2008. With it you can write code to generate code inside Visual Studio, and it is exactly what I'm searching for.

Here is the template:

   1: <#@ template debug="false" hostspecific="true" language="C#" #>
   2: <#@ output extension=".cs"  encoding="UTF8" #>
   3: <#@ assembly name="System.Core" #>
   4: <#@ assembly name="System.Xml" #>
   5: <#@ assembly name="System.Xml.Linq" #>
   6: <#@ import namespace="System.IO" #>
   7: <#@ import namespace="System.Text.RegularExpressions" #>
   8: <#@ import namespace="System.Linq" #>
   9: <#@ import namespace="System.Xml" #>
  10: <#@ import namespace="System.Xml.Linq" #>
  11: //------------------------------------------------------------------------------
  12: // <auto-generated>
  13: //     This code was generated by a tool.
  14: //
  15: //     Changes to this file may cause incorrect behavior and will be lost if
  16: //     the code is regenerated.
  17: // </auto-generated>
  18: //------------------------------------------------------------------------------
  19:  
  20: <#
  21: string appName = "ResXProxy Generator Template";
  22: string version = "1.0.3977.0";
  23: string ns = (string)System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("NamespaceHint");
  24: string resxFileName = Path.ChangeExtension(Host.TemplateFile, ".resx");
  25: string resxClassName = Path.GetFileNameWithoutExtension(Host.TemplateFile);
  26: string proxyClassName = string.Format("{0}ResourceProxy", resxClassName);
  27: XDocument document = XDocument.Parse(File.ReadAllText(resxFileName));
  28: #>
  29: namespace <#=ns#>
  30: {
  31:     using System.Globalization;
  32:     using System.Windows.Markup;
  33:  
  34:     /// <summary>
  35:     /// Represent a proxy class for "<#= resxClassName #>" resources
  36:     /// </summary>
  37:     [System.Diagnostics.DebuggerStepThroughAttribute()]
  38:     [System.CodeDom.Compiler.GeneratedCode("<#= appName #>", "<#= version #>")]
  39:     public class <#= proxyClassName #>
  40:     {
  41:         /// <summary>
  42:         /// Initializes the "<#= proxyClassName #>" class
  43:         /// </summary>
  44:         public <#= proxyClassName #>()
  45:         {}
  46:     
  47:         /// <summary>
  48:         /// Gets the current culture
  49:         /// </summary>
  50:         [System.CodeDom.Compiler.GeneratedCode("<#= appName #>", "<#= version #>")]
  51:         public CultureInfo CurrentCulture 
  52:         { 
  53:             get { return CultureInfo.CurrentCulture; } 
  54:         }
  55:  
  56:         /// <summary>
  57:         /// Gets the current UI Culture
  58:         /// </summary>
  59:         [System.CodeDom.Compiler.GeneratedCode("<#= appName #>", "<#= version #>")]
  60:         public CultureInfo CurrentUICulture 
  61:         {
  62:             get { return CultureInfo.CurrentUICulture; } 
  63:         }
  64:         
  65:         /// <summary>
  66:         /// Gets the current Xml Language property
  67:         /// </summary>
  68:         [System.CodeDom.Compiler.GeneratedCode("<#= appName #>", "<#= version #>")]
  69:         public XmlLanguage Language 
  70:         { 
  71:             get { return XmlLanguage.GetLanguage(CultureInfo.CurrentUICulture.Name); } 
  72:         }
  73: <# foreach(var item in document.Element("root").Elements("data")) 
  74:    { 
  75:         string name = EscapeName(item);
  76:     
  77:         if (item.Attributes("type").Count() == 0)
  78:         {
  79: #>
  80:  
  81:         /// <summary>
  82: <# if (item.Elements("comment").Count() == 1) { #>
  83:         /// <remarks><#= item.Element("comment").Value #></remarks>
  84: <# } #>
  85:         /// Gets the "<#= name #>" Property
  86:         /// </summary>
  87:         [System.CodeDom.Compiler.GeneratedCode("<#= appName #>", "<#= version #>")]
  88:         public string <#= name #> 
  89:         { 
  90:             get { return <#= resxClassName + "." + name #>; } 
  91:         }
  92: <# 
  93:         }
  94: }
  95: #>
  96:     }
  97: }<#+
  98: public string EscapeName(XElement item)
  99: {
 100:     string name = item.Attribute("name").Value;
 101:     return Regex.Replace(name, "[^a-zA-Z0-9_]{1,1}", "_");
 102: }
 103: #>

Using the template is really easy. First of all you have to configure the Silverlight application to be localizable ( you can find how to do)  and then create the required resx files. Finally you have to add the template using the same name of the main resource file but using the .tt extension. E.g. if your resx is called AppString.resx you have to call the template AppStrings.tt. Nothing else. Once you have added the template it automatically generates a class called AppStringResourceProxy you can easily reference from a XAML file and bind to the UI. Remember that every time you change the resx file you have to select "Run custom tool" from the context menu of the T4 template to generate the code again.

The generated class does not contains only the string properties but also expose a Language property. You can bind this property to the corresponding Language property of the page (the UserControl) and override the default culture that is usually set to "en-US". Doing this you will have also the Dates and numeric values converted to the right culture.

   1: <UserControl Language="{Binding Language, Source={StaticResource AppString}}" />

The tamplate works fine for Silverlight and Windows Phone. I've never tryied but I think it works also with WPF. Hope this helps.

Download Sample: Silverlightplayground.Localization.zip (96,3 KB)

Few thoughts on PDC 2010 and the Silverlight destiny…

2010-10-29T22:45:18+01:00 by Andrea Boschin

There is not any doubt, the words I read today in this article and the complete lack of Silverlight during the PDC 2010 has been for me an hard blow. I put a great part of my work in this technology, I immediately recognized as my best friend for fast and reliable developing of applications. And I'm still convinced about this argument, also after the fashion of HTML5 has taken the scene few months ago and now that it has been promoted to a primary actor of the most important conference of Microsoft. This does not mean I really believe that Silverlight has been put in the trashcan and HTML5 has been suddenly put in its place. This will be a story about whom we will know in the next months and I'm confident that what appear to be real now will be demonstrated false soon.

I say these words not as a fanboy, but simply thinking at the reasons that moved me away from the HTML and Javascript world where I was really active. I remember the days when I spent my time trying to make HTML pages similar across four browser. I remember the days when I filled my code with message boxes just to try to understand why my javascript code did not work. I remember the frustrating hours I wasted to try to make good layouts with a technology that is not born to develop applications but only to display rich hypertexts. Yes, all we have to remember that HTML is not for applications. And it is not cross-platform. Developers makes it so. 

I started my story in Silverlight with the very first beta of the version 1.0 and I still have in my ears the voices of people saying: "puah... you have to develop with Javascript... you are crazy!". And they were right, Silverlight 1.0 was ugly because it did not resolved the main problem of the developers, the need of having reliable code that is something Javascript cannot give us. And even Javascript libraries like jQuery can't. I would like to know where are the people that write testable code, the ones that use dependency containers, design patterns, or simply the most effective coding tecniques that have its main reason in protecting the code from errors (expecially runtime errors) and give it maintainability and flexibility. While Silverlight enforces all these tecniques, Javascript doesn't. So the question I asked myself today was: is it what the people really wants?

And my answer is no. I'm confident people like to have effective applications that they can develop in less of half the time they have to use with other technologies. HTML5 will be for sure an interesting thing, but none has to confuse it with a development platform. HTML is the sole language that can be used for websites, where search engines make the difference, but when someone seriously wants to develop "applications", it is an insane choice. Now, and watching at the story behind HTML probably forever. I want to remembers, closing this post, that HTML5 now is far to be final. Just during the demo at the PDC they showed how differently it behave on different browsers and to me none can seriously believe that the actors in the scene will not try to catch HTML5 and make it a weapon to kill the other competitors. This is already happening.

Categories:   News
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Silverlightbox released on Codeplex

2010-10-18T00:03:08+01:00 by Andrea Boschin

Few hours ago I released a new project on Codeplex called Silverlightbox. The purpose of this project is to create a replacement for the javascript lightbox, used widely in many websites to display images and slideshows. The project works adding a silverlight overlay to the page that is showed when an hyperlink to an image is hit.

The Silverlightbox I released is compatible with the javascript lightbox. You can easily change the scripts of lightbox with my scripts and it works seamless without any change to the HTML already tagged for the lightbox. To have a look at how it appear try to click one of these images

Also if I'm a strong fan of Silverlight I provided the Silverlightbox with a minimal fallback javascript version that take place when the client does not have the plugin installed.

How to use Silverlightbox

To add the Silverlightbox to your website you have to link few script in the page. They are a cascading style sheet, the main silverlightbox.js script and the silverlight.js. You have also to link jQuery from the microsoft CDN. jQuery is used for the fallback javascript and for the part that query the page to find links to attach. Here is the code you have to add to the page <HEAD>

<link href="slb/sllightbox.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.js"></script>
<script type="text/javascript" src="slb/silverlight.js"></script>
<script type="text/javascript" src="slb/silverlightbox.js"></script>


Once you have added the script to the page you can easily tag you hyperlink to show the silverlightbox. For this purpose you have to use the rel attribute and optionally specify a title attribute that is used to give a title to the displayed image. The code below show how to link an image to the Silverlightbox

<a href="http://blog.boschin.it/images/pics/DSC_6508.jpg" rel="lightbox" title="Dolphins 1">Show image</a>


Using a special syntax it is possible to create collection of images displayed ad slideshows. A slideshow have the navigation controls and let the user to move alogn the images without closinge the Silverlightbox. Here is how to create a slideshow

<a href="http://blog.boschin.it/images/pics/DSC_6511.jpg" rel="lightbox[dolphins]" title="Dolphins 2">Show image 1</a>
<a href="http://blog.boschin.it/images/pics/DSC_6516.jpg" rel="lightbox[dolphins]" title="Dolphins 3">Show image 2</a>
<a href="http://blog.boschin.it/images/pics/DSC_6519.jpg" rel="lightbox[dolphins]" title="Dolphins 4">Show image 3</a>
<a href="http://blog.boschin.it/images/pics/DSC_6522.jpg" rel="lightbox[dolphins]" title="Dolphins 5">Show image 4</a>

The code create a collection called "dolphins". You can have mltiple collections in a page using different names to group images each other.

Futures

I would want to continue the development of the Silverlightbox that now comes in the minimal release that cover the same features of the javascript counterpart. My intent is to add some interesting features:

1) autoplay of slideshows
2) support for video
3) customizable easing in and out
4) themes

Please let me know if there are other features you like and if you find any issue with the Silverlightbox. For this purpose please use the issue tracker on codeplex.

Link: http://silverlightbox.codeplex.com/

Tags:   , ,
Categories:   News
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

WP7 Fast Tips: Load (decode) and Save (encode) Jpeg files

2010-10-15T11:40:05+01:00 by Andrea Boschin

Notice: I've added the new category "WP7 Fast Tips" to collect fast tips I found while developing my Windows Phone Applications. You Don't expect only great tips in this category but also simple things I need fo remember or I found with some difficulties :)


Working on an application I hope to publish soon on the marketplace, I have the need to save an image from a WriteableBitmap instance into a Jpeg file. It was not an easy search but finally I found a couple of methods, added as Extension Methods to the WriteableBitmap class itself. If you need to encode a jpeg to a byte array you can use this code:

   1: public byte[] EncodeToJpeg(WriteableBitmap wb)
   2: {
   3:     using(MemoryStream stream = new MemoryStream())
   4:     {
   5:         // this is Extensions.SaveJpeg() method
   6:         wb.SaveJpeg(stream, wb.PixelWidth, wb.PixelHeight, 0, 85);
   7:         return stream.ToArray();
   8:     }
   9: }

The parameters of the SaveJpeg method require a stream to write to, the size of the bitmap to generate and the quality from 0 to 100. The fourth parameter, called orientation, currently is not used and you can set it to 0 (zero).

The counterpart of the SaveJpeg methos is LoadJpeg that you can use to take a Jpeg file and load it into a WriteableBitmap instance. A very useful feature. If you need to write the Jpeg to the MediaLibrary probably the better is to pass the generated stream directly to the Save method.

Tags:  
Categories:   TIPS | Windows Phone 7
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

Join Silverlight Firestarter!

2010-10-14T21:53:37+01:00 by Andrea Boschin

SLFirestarter_150X240

Silverlight Firestarter is a global event, stremed from Microsoft and presented by Scott Guthrie. During the event you can follw interesting sessions about Silverlight, k questions ad be in touch with your favorite technology.

It is an important event you cannot miss!

When: Thursday, December 2, 2010 8am to 5pm PT

Where: Microsoft corp, Redmond or Streamed Online

To register for the event follow this link and apply for in person or online registration form

http://www.silverlight.net/news/events/firestarter/

Capture

Tags:  
Categories:   News
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed

A generic enum converter to map values...

2010-09-03T16:38:49+01:00 by Andrea Boschin

Many times I have to deal with enumerated values with databinding, and often this requires  the writing of a converter to map the enum to something else. As an example you can have a Status enum and you need to transform it to a color (or a brush) in the UI, or you have a series of values from the enumerator and need to change it to an image when it is presented to the user.

Finally these days I found a generic solution to these problems that let me create a mapping from a value (an enumerator, a series of integers, of also a boolean) to an instance of another object. To give you an example think at having this enumerator:

   1: public enum MessageType
   2: {
   3:     Normal,
   4:     Urgent,
   5:     Critical
   6: }

We want to map the values to a series of colors having White for Normal, Orange for Urgent and Red for Critical. Since usually you can override IValueConverter and write a specific converter that handles this enum I found useful to create a parametric value converter that lets me write the code below:

   1: <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   2:              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   3:              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
   4:              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
   5:              xmlns:cv="clr-namespace:SilverlightPlayground.Converters;assembly=SilverlightPlayground"
   6:              mc:Ignorable="d" x:Class="SilverlightPlayground.MyApplication.Shell" d:DesignWidth="456">
   7:     <UserControl.Resources>
   8:         <cv:EnumConverter x:Key="mapTypeToBrush">
   9:             <cv:EnumConverter.Items>
  10:                 <SolidColorBrush Color="#00000000" />
  11:                 <SolidColorBrush Color="#FFFF9900" />
  12:                 <SolidColorBrush Color="#FFFF0000" />
  13:             </cv:EnumConverter.Items>
  14:         </cv:EnumConverter>
  15:     </UserControl.Resources>
  16:     <Grid x:Name="LayoutRoot">
  17:         <Rectangle Fill="{Binding ReveivedMessageType, Converter={StaticResource mapTypeToBrush}}" Width="100" Height="100" />
  18:     </Grid>
  19: </UserControl>

The beautiful of this converter is that with a single converter you can create a series of mappings in the App.xaml resources and share them across all the applications and centralize the conversion of application wide enums in a single position. The code of the converter is really simple and straightforward:

   1: public class EnumConverter : IValueConverter
   2: {
   3:     private List<object> items;
   4:  
   5:     public List<object> Items 
   6:     { 
   7:         get
   8:         {
   9:             if (items == null)
  10:                 items = new List<object>();
  11:  
  12:             return items;
  13:         }
  14:     }
  15:  
  16:     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  17:     {
  18:         if (value == null)
  19:             throw new ArgumentNullException("value");
  20:         else if (value is bool)
  21:             return this.Items.ElementAtOrDefault(System.Convert.ToByte(value));
  22:         else if (value is byte)
  23:             return this.Items.ElementAtOrDefault(System.Convert.ToByte(value));
  24:         else if (value is short)
  25:             return this.Items.ElementAtOrDefault(System.Convert.ToInt16(value));
  26:         else if (value is int)
  27:             return this.Items.ElementAtOrDefault(System.Convert.ToInt32(value));
  28:         else if (value is long)
  29:             return this.Items.ElementAtOrDefault(System.Convert.ToInt32(value));
  30:         else if (value is Enum)
  31:             return this.Items.ElementAtOrDefault(System.Convert.ToInt32(value));
  32:  
  33:         throw new InvalidOperationException(string.Format("Invalid input value of type '{0}'", value.GetType()));
  34:     }
  35:  
  36:     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  37:     {
  38:         if (value == null)
  39:             throw new ArgumentNullException("value");
  40:  
  41:         return this.Items.Where(b => b.Equals(value)).Select((a, b) => b);
  42:     }
  43: }

The converter has a list of items it use to make the conversion of integer values. It maps the integer to the index of the list and returns the n-th element found in the array. I didn't handled the out of bounds exception just because the errore returned to the user by the converter is already good to understand what it happen. The converter itself can handle both the directions if the Equals method is correctly overrided.

Finally, I  supported boolean values so it is possible to pass to the converter true/false and having it select the items from a list of two elements. This let me also map the Visibility to boolean values (that is a pretty frequent situation):

   1: <cv:EnumConverter x:Key="bool2Visibility">
   2:     <cv:EnumConverter.Items>
   3:         <Visibility>Collapsed</Visibility>
   4:         <Visibility>Visible</Visibility>
   5:     </cv:EnumConverter.Items>
   6: </cv:EnumConverter>

As you can see the trick is really simple but as usual simple things are the most beautiful and useful. I hope someone can judge this tip good to spare time. It has been very great for me.

FormsAuthentication and ClientHttpStack with mixed applications

2010-08-30T16:41:47+01:00 by Andrea Boschin

If you ever tried to have mixed applications, with some regular ASP.NET pages and a bunch of Silverlight applications, where the forms authentication is made with a traditional ASP.NET login page, you have for sure found that you are forced to use the BrowserHttp stack into the Silverlight applications because the FormsAuthentication cookie is not shared between the ASP.NET page and the new ClientHttp stack that is available since Silverlight 3.0.

Since the new ClientHttp stack for many reasons is a huge improvement, is would be a beautiful thing being able to use this stack every time there is the need to place HTTP calls. Finally I found a way to share this cookie across the two stacks, but I want to warn you that the sole way to accomplish this task require a little "dirty hack", that someone might consider unacceptable while it opens some minor security concerns I will detail at the end of the post.

Before continue reading this post please have in mind that my suggestion is to always use the BrowserHttp stack in these scenario, until you do not really need the new stack, e.g. if you have to use some special verb or for some other particular reason.

The dirty hack explained

The first thing you have to know is that when you are using the ClientHttp stack you are free to access the cookies issued by the server and it is also possible to add some cookies to attach to a call. The task we would have to accomplish is simply to read a cookie (often called .ASPXAUTH) from the BrowserHttp stack and add it to the ClientHttp stack and it may seems and easy task.

Unfortunately the BrowserHttp Stack prevent us from accessing the cookies. The cookies management is one of the features that has been added by the new ClientHttp stack and there is not any way to pump out them from the old one.

So my first try was to use the HtmlPage.Document.Cookies property, as I found in some examples on the Internet. Perhaps this may work when the authentication cookie is issued by a custom authentication system, but with FormsAuthentication it is another failed try because the cookies issued by the ASP.NET engine are HttpOnly. This attribute, added since IE6 SP1, prevents the browser scripts - and Silverlight is considered a client script - from accessing these cookies that remain hidden.

So, how can we share these cookies? The only thing you can do is to add the cookie to the InitParams collection when you initialize the plugin in the html page. You have to change this page to be an aspx page and then you can create two keys into the InitParams collection like the following:

   1: public string GetFormsAuthenticationCookie()
   2: {
   3:     return string.Format(
   4:         "FormsCookieName={0},FormsCookieValue={1}",
   5:         FormsAuthentication.FormsCookieName,
   6:         this.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
   7: }

Then in the plugin I would like to have a centralized class reponsible of creating the cookie and adding it to each server call I do. First of all, if you are using WCF you have to enable the CookieContainer from the ServiceReferences.ClientConfig file. You have to add an attribute that exists only in the Siverlight side of the configuration:

   1: <basicHttpBinding>
   2:     <binding name="BasicHttpBinding_IWCFService" 
   3:               maxBufferSize="2147483647"
   4:               enableHttpCookieContainer="True"
   5:               maxReceivedMessageSize="2147483647">
   6:         <security mode="None" />
   7:     </binding>
   8: </basicHttpBinding>

The enableCookieContainer attribute initializes an instance of an IHttpCookieContainerManager into the WCF client an this allow us to manage cookies using the CookieContainer collection. Now we can write a simple application service to put into the app.xaml that we can use to instantiate and initialize the client. The reason of creating an application service is to have a common place where initialize a shared cookie container that reads the InitParam and add the received cookies into it:

   1: public class ClientCreatorService : IApplicationService
   2: {
   3:     public static ClientCreatorService Current
   4:     {
   5:         get
   6:         {
   7:             return Application.Current.ApplicationLifetimeObjects.OfType<ClientCreatorService>().Single();
   8:         }
   9:     }
  10:  
  11:     private CookieContainer SharedCookies { get; set; }
  12:  
  13:     public void StartService(ApplicationServiceContext context)
  14:     {
  15:         this.SharedCookies = new CookieContainer();
  16:         string formsCookieName = context.ApplicationInitParams["FormsCookieName"];
  17:         string formsCookieValue = context.ApplicationInitParams["FormsCookieValue"];
  18:         this.SharedCookies.Add(new Uri(Application.Current.Host.Source, "../"), new Cookie(formsCookieName, formsCookieValue));
  19:     }
  20:  
  21:     public K CreateClient<T, K>()
  22:         where K : ClientBase<T>, new()
  23:         where T : class
  24:     {
  25:         K client = new K();
  26:         IHttpCookieContainerManager cookieManager = client.InnerChannel.GetProperty<IHttpCookieContainerManager>();
  27:         cookieManager.CookieContainer = this.SharedCookies;
  28:         return client;
  29:     }
  30:  
  31:     public void StopService()
  32:     {}
  33: }

During the initialization the ClientCreatorService initialize the SharedCookies with the FormsCookieName and FormsCookieValue. Then the generic CreateClient methid is able to instantiate the required client and add the SharedCookies to it. The usage of the Application Service is pretty simple. Here is how to instantiate the client and place a call:

   1: WCFServiceClient client = ClientCreatorService.Current.CreateClient<IWCFService, WCFServiceClient>();
   2: client.GetIdentityCompleted += new EventHandler<GetIdentityCompletedEventArgs>(client_GetIdentityCompleted);
   3: client.GetIdentityAsync();

If you try the code you will find that the GetIdentity method is able to retrive the membership identity from the HttpContext.Current.User property. This means your service runs in an authenticated context.

What is the drawback?

When you make a dirty thing you have to be aware that there is always almost a drawback. In this case the problem is that the injection of the authentication cookie in the InitParams opens a subtle security concern that is mitigated by the fact that the informations we are disclosing are already public even before my trick was up and running. The use of HttpOnly cookies for authentication is an important improvement that prevent the use of XSS attacks. Having the cookie injected in the page, re-open the window to some pre-IE6 SP1 scripts that could try to access the InitParams collection from javascript and simulate the authentication to the system like our Silverlight application actually does.

This problem must be always in your mind and you have to put on the scale both the advantage of having the ClientHttp working and the security concerns of this trick. My hope is that the Silverlight team will be able to solve this issue in next releases of the plugin, so we can rely on a secure implementation and avoid dirty tricks.

Categories:   Networking | TIPS
Actions:   E-mail | del.icio.us | Permalink | Comments (0) | Comment RSSRSS comment feed