Tuesday, November 24, 2009

MEF Contrib for Silverlight 3 (Unofficial)

I’m happy to announce that I’ve completed porting the most recent MEF Contrib (0.7) project to SL3. The project has also been updated to use the most recent MEF release which is beta 2 (Preview 8) as of this writing. All the unit tests from the project pass in the SL environment, here are the screenshots:

image image image

Before I dig into the changes I had to make in order to make it work on SL3, I will focus on NUnit for SL.

As all of you probably know, it is possible to run NUnit tests in SL environment. Microsoft has released a library called Microsoft.Silverlight.Testing which enables developers to execute tests on SL’s CLR. This library ships out of the box with the implementation of MS Tests. However, its extensibility allows to write custom providers for other testing frameworks. Jeff Wilcox wrote a post about running NUnit tests in the SL environment here. He did two things: ported a subset of NUnit to SL, and wrote a provider which enables running NUnit tests using Microsoft.Silverlight.Testing framework. However, his NUnit implementation is very limited, so I googled a little and found a guy who ported NUnit 2.5.1 to SL (you can find his post here). So, for the testing purposes I used mentioned NUnit 2.5.1 SL port together with a provider developed by Jeff. I must admit here, that I’m not sure whether all the features from NU 2.5.1 work correctly in the SL environment. Hopefully, it seems that all the Assert methods including Assert.That and Throws work as expected.

As far as MEFContrib project is concerted, I didn’t have to introduce many modifications. MefContrib.Extensions.Generic project runs without any changes. MefContrib.Integration.Unity project didn’t need to be changed in terms of its implementation. However, all stubs used in unit tests were declared as internal, and it seems MEF for SL has some troubles while instantiating non public members (or SL policy doesn’t allow this?) so most tests were failing. Fortunately, changing access to public repaired everything :) The story is a bit different for the MefContrib.Models.Provider project. This project adds to MEF custom provider model with three programming models built on top of it. These three programming models are

  • Attributed – as it name suggest, parts are registered using attributes,
  • Configurable – parts get registered via App.config,
  • Fluent – parts are registered through method invocation.

The problem lays in the Configurable programming model, because it is implemented using System.Configuration namespace, which is not available to SL programmers. Thus, MefContrib.SIlverlight does not support this model.

The last trouble I had was with two test, which reside in MemberInfoServicesTests test fixture, namely

  • GetMemberInfoShouldReturnMemberIfMemberNameIsSupplied,
  • GetMemberInfoShouldReturnTypeIfMemberNameNotIsSupplied.

Both unit tests test MemberInfoServices class. Both were throwing an exception telling that the test assembly (MefContrib.Models.Provider.Tests) cannot be loaded or the assembly has already been loaded but the versions doesn’t match. To cut the long story short, it turned out that the following code was the root cause (code like the presented below is executed in MemberInfoServices.GetMemberInfo method in both tests) :

Type.GetType("MefContrib.Models.Provider.Tests.FakePropertyPart, MefContrib.Models.Provider.Testsl", false, true)
Don’t know why this doesn’t work. However, a simple modification like follows did the job :)

Type.GetType("MefContrib.Models.Provider.Tests.FakePropertyPart, MefContrib.Models.Provider.Tests, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", false, true)
To maintain separate versions of both tests for regular CLR and SL, I used SILVERLIGHT compiler flag.

Please note that this version is an unofficial release, not available through codeplex.com site. However, I will put an effort to make this an official release or make next MefContrib release based on this one.

Full source code is available on my code gallery here.

Saturday, November 21, 2009

Watermark effect for WPF’s TextBox and ComboBox controls

Update

I have updated this sample to contain the watermark effect for the ComboBox control too. Its implementation is almost identical to the TextBox’s one. Here are the screens showing the effect being applied to the ComboBox control:

image image

And here comes the original post.

In this post I’m going to show a nice watermark effect for WPF’s TextBox control. Sample application (link to the sources at the end of this post) looks as follows:

image image

As you can see, non focused text box containing no text, displays a useful clue to the user informing what kind of information should be entered. Focusing a textbox immediately removes that clue.

There are probably as many ways to introduce such a behavior as there are developers all over the world :) However, one particular solution is to be considered in this case. The above effect has been achieved using adorners. The adorner used for the effect contains a single TextBlock with optional style applied to it. A good introduction to adorners is available here.

The effect has been implemented using attached behavior pattern, so no inheritance was introduced.

Using the behavior is a piece of cake. Here’s how to apply the behavior to a TextBox control:

<TextBox Height="25" Margin="0,5,0,5"
Behaviors:WatermarkTextBoxBehavior.EnableWatermark="True"
Behaviors:WatermarkTextBoxBehavior.Label="Label"
Behaviors:WatermarkTextBoxBehavior.LabelStyle="{StaticResource watermarkLabelStyle2}" />

The first property, EnableWatermark, as its name suggests, enables the effect ;) The Label property holds the text to be displayed as a watermark. Finally, the LabelStyle property contains the style to be applied to the label. And the style, defined in Window’s Resources collection, might look as follows:


<Style x:Key="watermarkLabelStyle">
<Setter Property="TextBlock.Foreground" Value="{x:Static SystemColors.ControlDarkBrush}" />
<Setter Property="FrameworkElement.Opacity" Value="0.8" />
<Setter Property="TextBlock.FontSize" Value="12" />
<Setter Property="TextBlock.FontStyle" Value="Italic" />
<Setter Property="TextBlock.Margin" Value="8,4,4,4" />
</Style>

I’m not going to discuss any implementation details here since the adorner itself is trivial, and the behavior is quite easy as well. Maybe I will tell you that the watermark is displayed when the TextBox fires its Loaded event. Why is that important to know? Keep reading… ;P Besides, skim the code and you immediately know how stuff works :)

Finally, one thing, which deserves to give attention to, is control loading and the adorner layer (adorner layer is a place always rendered over the control where all adorners for that control get displayed). When a control is contained within a portion of UI that is being displayed, but the control itself is not visible, it normally fires Loaded event, but because it is not visible, it has no adorner layer! So don’t assume that call to AdornerLayer.GetAdornerLayer(Visual) always returns the adorner layer! This is why the sample shown above contains a TabControl – the second tab, named Tab 2, contains a TextBox with the watermark effect applied to it, and this still works :)


As always, code sample is available through my Code Gallery here.