Silverlight Templating: Bending Controls to Your Will

Posted by Dave Bouwman | Posted in Sample Code, Silverlight | Posted on 22-06-2009

0

I’m building an forms-over-data application that needs to control edit access based on the user’s role, and the active item’s workflow status.

Download Sample Code

When building similar functionality in ASP.NET MVC applications, we’ve handled this scenario by having the server render a partial page, and based on the user’s edit access, we emit form elements (text areas, select boxes etc), or just content. The partial is injected into a containing DIV element, and all is well.

Of course, this is not an option with Silverlight – well I guess we could build separate read-only and read-write Views, but that would be a bunch more work. Why not leverage the IsEnabled property instead – that should work, and it’s ok from a sematic point of view (purists may want to sub-class all the controls and add a "IsReadOnly" property and use that, but I’m a pragmatist – IsEnabled is a reasonable compromise).

The only problem is that by default the control’s content is grayed out when it is disabled (shown below). This makes the "Read Only" state less than "readable"…

sl-disabled

With WinForms, we’d just be out of luck. But since this is XAML, we can override the control’s template and change it’s look and feel for the various states.

Since we’ll want these styles accessible across our entire application, we’ll be adding the templates into App.xaml. But before we do that we’ll need to add a namespace for the visual state manager (vsm)

 

<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Class="sl_templating.App"
             xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
             >

 

From there, we grab the default template from MSDN ( http://msdn.microsoft.com/en-us/library/dd334408(VS.95).aspx ) and assign it a key so we can force our combo box control to load it’s template from App.xaml instead of it’s dll.

<Style TargetType="ComboBox" x:Key="DTSComboBox">
...
</Style>

Then in our page (or to be more specific our Views) we tell the combobox to load it’s style from the static resource

<ComboBox x:Name="cboComboBox" IsEnabled="True" Grid.Row="0" Margin="5,5,5,5" 
       Style="{StaticResource DTSComboBox}">
       <ComboBoxItem Content="Thing One"/>
       <ComboBoxItem Content="Thing Two" IsSelected="True"/>
       <ComboBoxItem Content="Thing Three"/>
   </ComboBox>

 

Now it’s time to have fun – we change the template to match what we need. For the first cut here’s what I was looking for:

Combo Box: When disabled, gray out the drop down button, and the border, but leave the text readable

TextBox: Gray out the border, but leave the text readable.

Visual States

For this sort of thing, we are going to be modifying the visual states for the controls. The state we are interested in is called (not surprisingly) "Disabled". So we locate this in the Visual State Manager section of the control template…

<vsm:VisualState x:Name="Disabled">
    <Storyboard>
        <DoubleAnimation Storyboard.TargetName="DisabledVisualElement"
                         Storyboard.TargetProperty="Opacity" To=".7" Duration="0"/>
    </Storyboard>
</vsm:VisualState>

and we see that when the control’s state is changed to Disabled, a Storyboard with the name "DisabledVisualElement" is called. So we go and locate that…

<Border x:Name="DisabledVisualElement"
        Background="#A5F7F7F7"
        BorderBrush="#A5F7F7F7"
        BorderThickness="{TemplateBinding BorderThickness}"
        Opacity="0" IsHitTestVisible="False"/>

And from the looks of this, we can see that the Background and Border are set to a lovely gray (F7F7F7). Since we know that text content of a control is rendered in the Background color, we simply remove that property.

<Border x:Name="DisabledVisualElement"
        BorderBrush="#A5F7F7F7"
        BorderThickness="{TemplateBinding BorderThickness}"
        Opacity="0" IsHitTestVisible="False"/>

Voila! The disabled state for our TextBox will leave the text color as is, and just gray out the border, thus giving a visual cue that it’s read-only.

For the ComboBox, it’s a similar process, but complicated by the fact that the ComboBox is made up of multiple parts. We can leave the ToggleButton as is – it gray’s itself out nicely, and that’s fine with us. The other default behavior is to draw the control as a filled rectangle with a opacity set. This is what "grays" out the ComboBox item. Instead of setting a Fill, we just set the Stroke to a nice gray (the illustrious F7F7F7 again).

<Rectangle x:Name="DisabledVisualElement"
           RadiusX="3" RadiusY="3"
           Stroke="#A5F7F7F7" Opacity="0" IsHitTestVisible="false" />

That’s it. Now our controls enable & disable nicely, and the content is still readable.

sl-disabled-templatesd

This is clearly just scratching the surface of what you can do with templating, and I’m sure I’ll be digging into more controls like this, but it’s a nice capability to have.

Building Line-of-Business Apps with Silverlight 2.0: Part 1

Posted by Dave Bouwman | Posted in .NET, Silverlight | Posted on 10-06-2009

1

While I’ve been playing around with Silverlight for a while now, the time has come to build something a little bigger with it. Here’s the situation:

  • I’m Converting an Access/SQL Server application over to use a Silverlight 2.0 front end with ADO.NET Data Services on the back.
  • Database already exists, with 83 tables, including users and roles.
  • We need custom Authentication and Authorization services to control who can view/edit data
  • Application will have about ~30 User controls, which will be composed into about ~20 screens

Given this situation, I needed to find a framework that’s proven instead of trying to hack something up myself.

My goals were:

  • the client side Silverlight code needs to be unit testable
  • clean Separation of Concerns where ever possible – both to support unit testing and so we use "fakes" during development
  • Something that’s documented so myself and others on the team can figure it out.

After some Googling, it came down to two options:

Hand-Rolled Model-View-ViewModel (MVVM) or the Composite Application Library (aka Prism v2) from Microsoft Patterns and Practices.

Having used Enterprise Library, I knew that the MS Patterns and Practices stuff would be complex, but it would work. In an effort to keep things simple, I took a peek at "raw" MVVM first.

I’ll also mention that Nikhil Kothari has created Silverlight.FX – “light-weight application framework for building Rich Internet Applications with Silverlight 2”. While I have huge respect for Nikhil, and the project looks promising, it seemed a little too big to take on with just his blog posts and source code as documentation.

"Raw" MVVM in Silverlight 2.0

Conveniently there is a fair bit of information on MVVM floating around, so it was relatively easy to get the gist of things. One of the best resources was this screen cast by Erik Mork at Silver Bay Labs.

silverbay

Erik walks through the basics of the pattern by referencing an article by Shawn Wildermuth in MSDN Magazine, and then shows how to build out a very simple sample application based on the article’s code, and shows how to test the ViewModel using the Silverlight test harness.

As Erik notes here (he uses a media player that sync’s the code display with the video, and it’s bookmarkable!), the down-side of using "raw" MVVM in Silverlight is that you still need to have some "goop" in the code behind that fires events back into the ViewModel (due to the lack of "commanding" in vanilla Silverlight). Ideally we’d like to avoid the code-behind and have the ViewModel linked to the View (XAML) declaratively.

Another downside is that while MVVM provides a pattern for the individual views, it does not provide much infrastructure to create an application that’s composed of many views – I’d have to roll this myself or hack parts from a variety of samples – not idea. Conveniently though, we can use MVVM with Prism…

Composite Application Library aka Prism

Many people have heard of the “Old” Composite Application Block (aka “CAB”), and that alone could be enough to scare some people off. Although it shares a similar name, the Composite Application Library is much different. Prism is a set of components, services and patterns that can help with the construction of  MVVM Silverlight applications. It includes:

  • The Microsoft Unit Inversion of Control Container
  • Commanding for Silverlight (declaratively linking the ViewModel to the View in XAML)
  • Centralized Event Aggregation (makes loosely coupled designs much easier)
  • Support for UI composition from multiple views

Getting Started with Prism

As like most other things from Microsoft Patterns and Practices, this stuff is both complex and well documented. In fact, the Guidance is simply amazing. It has overviews of all the key components, solid descriptions of how/when to use them, as well as “Quick Start” project that show the concept in action. They also have a “reference implementation” which seems to combine all possible aspects and combinations in one project. I’d hold off on looking at this until you’ve got a good handle on the individual components though, as it’s pretty hairy.

But to get a good idea of how Prism works, there are some good videos I recommend checking out:

Erik Mork of SilverBayLabs.org has a couple of great really simple intro videos. These were great for introducing the basic components – the shell, models, viewmodels and how they relate.

Channel9.com has a 4 part series with Bob Brumfield and Erwin van der Valk from patterns and practices showing to build a modular application using Prism.

At this point I’ve managed to get my app’s structure laid out, I’ve got login capabilities which correctly add cookies which allow access to secured services, and I’ve got a few rough modules and a rough means to transition between them. Learning Silveright, XAML, Expression Blend, MVVM, Unity, and Prism all at once made for a pretty harsh learning curve, but I’m past the roughest parts. In some cases I’ve departed from MVVM due to some limitations on databinding (twoway data binding to a PasswordBox is apparently verboten), and I have a little “goop” in my View code-behinds, but I think these are corner cases, and the “main” modules (the ones with the business logic) should be MVVM.

When I get some time, I plan on posting some notes and sample code for things which were difficult to understand, or implement.

Agile Workshop on June 26th in Denver

Posted by Dave Bouwman | Posted in Uncategorized | Posted on 02-06-2009

1

Venturesome seagull Just a quick note that Brian Noyle and I will give a one day Agile Project Management training workshop on Friday, June 26, 2009 in Denver, CO.  This course will cover both project management practices and development/engineering practices. While we *talk* about developer tools & practices, this is not just for developers – the whole day is equally pertinent to technical and management staff.

We’ll begin with an introduction to agile practices and rapidly progress to specific methodology examples (Scrum), cover roles and responsibilities, project controls, and how to scale the agile process in your organization. 

In addition, we’ll introduce specific software development processes that mesh well with the agile process including automation for code documentation and unit testing, design patterns, refactoring tools, and automated builds and continuous integration.  Throughout the course we’ll give you specific examples, the good, the bad, and the ugly, from our own experiences using the methodology in our shop. We’ll also have hands-on exercises so you can try out some of the ideas we are discussing.

Course Details:

Course Material: Introduction to Agile: Project Management and Development

Date: Friday, June 26, 2009

Location: USGS Mtg Room, Fed Center, Lakewood CO (suburb of Denver for those not from Colorado)

More Information: www.rm-urisa.org/news.html

Please use the “more information” link above to read the full course abstract and get additional details including how to register, maps of how to get there, etc. 

Hope to see some of you in June!