Microsoft Silverlight 5: 9 New Features That Benefit Line-of-Business Applications

Microsoft Silverlight 5: 9 New Features That Benefit Line-of-Business Applications

Explore 9 new features in Microsoft's Silverlight 5—implicit data templates and more—that boost LOB app development

Silverlight 5 brings a robust set of new features to the table for developers building media, marketing, and line-of-business (LOB) applications. Although new capabilities in Silverlight 5 such as XNA 3D, enhanced audio and video features, and 64-bit support have garnered a lot of attention (and for good reason), Silverlight 5 offers key benefits to LOB application developers. These benefits include enhanced data binding, better debugging, implicit data template support, vector printing, and others. In this article I'll focus on key LOB features available in Silverlight 5 and demonstrate how they can be used in applications. Let's start by talking about one of my favorite new features: implicit data templates.

Implicit Data Templates

Data templates, an important part of Silverlight LOB applications, allow data to be formatted and displayed in a variety of ways. Prior to Silverlight 5, developers had to use keys defined in styles or templates to apply data templates to controls. Although this approach worked fine, the ability to apply templates implicitly based on bound types has been a popular feature request, especially as that functionality is already part of Windows Presentation Foundation (WPF). Implicit data templates allow a type such as Person to be associated with a template. As a control binds to a collection of Person objects, the data template will implicitly be used by the control, allowing you to avoid explicitly defining data template keys.

So how does it work? A new DataType property has been added to the DataTemplate object, which is used to define the specific type the template is associated with. Figure 1 shows an example of using the DataType property. This example includes a ComboBox that is bound to a collection property named People. No explicit data template is hooked to the ComboxBox. Instead, the data template is associated with a Person type, and its FirstName and LastName properties are bound to TextBlock controls. As Person instances are bound to the ComboBox control, the data template is automatically applied and used to render the FirstName and LastName property values. This is done without explicitly defining a key on the data template, as with Silverlight 4 and earlier.



...


    
        
        
    
    

...


What's great about this new functionality is that if a child type derives from Person and is bound to the ComboBox (such as a PremiumCustomer type), its implicit data template will be used automatically if available. If the PremiumCustomer type doesn't have a data template, the Person data template will be used. Figure 2 shows how multiple data templates can be defined for object hierarchies.


    
    
    
    



    
    
    
    

In this example, PremiumCustomer types will be displayed with a yellow background to highlight data in the ComboBox, as Figure 3 shows.

Figure 3: Implicit data templates in action
Figure 3: Implicit data templates in action

Ancestor RelativeSource Binding

If you've ever wanted to bind a child object property to a parent object property but realized you couldn't do so easily in XAML, you'll be happy to know that Silverlight 5 adds support for ancestor RelativeSource binding. This new type of binding allows a child to bind to a parent (or an ancestor higher up in the hierarchy) by using the new RelativeSource binding. Additional properties such as AncestorType and AncestorLevel can also be used along with RelativeSource to determine the type of parent object to look for as well as how many levels up it is from the child.

RelativeSource binding is especially useful when working with data templates where a child in the template needs access to data exposed by the parent. Figure 4 shows an example of how ancestor RelativeSource bindings can be used.


    
    
    
        
        
        
        
    
    
    
    
    

Looking at the code in Figure 4, you'll notice that the data template contains a ComboBox that is used to show states and a TextBlock control that handles rendering the LastName property of a Person type. The problem is that at runtime the ComboBox in the data template will have access only to the Person object's properties (since the Person object becomes the data context as each item of the Listbox is bound). That's a problem because the ComboBox needs to display states.

To allow the ComboBox control's ItemSource property to bind to the parent control's DataContext.States property (the view model object's States property, in other words-see Figure 5), an ancestor RelativeSource binding is used. This is done by setting the RelativeSource property of the binding to {RelativeSource AncestorType=ListBox, AncestorLevel=1}. As the ComboBox is bound, it will get its ItemsSource value from the ListBox control's DataContext, then navigate to the States property. Although there are other workarounds to this type of binding challenge in XAML, ancestor RelativeSource binding adds important functionality that has been missing in previous releases of Silverlight.

Debugging Bindings in XAML

LOB applications often have many data-binding expressions defined in XAML that handle binding object properties to control properties by using one- or two-way binding modes. While Silverlight's XAML data-binding story is excellent, the same can't be said for debugging XAML data-binding expressions in Visual Studio with Silverlight 4 and earlier. Unless you were skilled in using Visual Studio's Output window, you often felt like you were looking for a needle in a haystack when trying to get to the bottom of a data-binding problem.

Silverlight 5 and Visual Studio 2010 (with SP1) provide integrated XAML debugging support to greatly simplify the process of finding data-binding issues. Simply set a breakpoint on your data-binding statement in the XAML file, and it will be hit at runtime. You have full access to the important debugging windows such as Watch, Autos, and Locals. Figure 6 shows an example of setting an XAML breakpoint in Visual Studio, and Figure 7 shows the Locals window in action once a breakpoint has been hit.

Figure 6: Support for debugging data-binding expressions directly in XAML files in Visual Studio 2010 with SP1
Figure 6: Support for debugging data-binding expressions directly in XAML files in Visual Studio 2010 with SP1

Looking at Figure 7, you'll see that the BindingState field in the Locals window has an Action property value set to UpdatingTarget, which means that the target control is being updated. The Action property changes to UpdatingSource when a value is moving between a control and a source object as with a two-way binding. When you drill down into the BindingState object, you'll also see a FinalSource property that shows the data that's being bound to the target control. In this example, two Person objects are being bound to a ListBox control. In addition to the Action and FinalSource properties, the Error property is available as is the source object property (People in this example) participating in the data-binding operation.

Figure 7: Using the Locals window to view information about a data-binding expression
Figure 7: Using the Locals window to view information about a data-binding expression

This new debugging functionality provides a huge productivity boost to developers trying to resolve data-binding issues in their Silverlight applications. The days of scrolling through the Output window to see why a data-binding expression is failing are over.

Elevated-Trust Enhancements

Silverlight 4 introduced the concept of elevated trust, which allowed a Silverlight application running out of browser to perform tasks such as accessing the hard drive and integrating with COM components installed on the client machine. Silverlight 5 adds several new enhancements to elevated-trust applications, including the ability to perform PInvoke calls (low-level calls to the operating system API), run elevated-trust applications in the browser, and run the WebBrowser control while in a browser. Out-of-browser (OOB) applications have also been enhanced to support multiple ad-hoc windows. This new functionality allows in-browser and OOB applications to perform tasks typically reserved for traditional desktop applications, such as accessing USB devices and spawning windows that can run on multiple monitors.

The process of enabling elevated trust is the same as it was previously in Silverlight 4. Right-click on the Silverlight project and check the Enable running application out of the browser check box. Once the check box is checked, you can click the Out-of-Browser Settings button, then check the Require elevated trust when running outside the browser check box located at the bottom of the dialog, as shown in Figure 8.

Figure 8: Enabling elevated trust in a Silverlight 5 application
Figure 8: Enabling elevated trust in a Silverlight 5 application

Using PInvoke in Silverlight 5

After elevated trust is enabled, you can use new Silverlight 5 functionality such as PInvoke in an application. PInvoke calls allow a Silverlight application to call into unmanaged APIs exposed by the Windows OS. By using PInvoke, you can gain low-level access to functionality that was off limits before. Figure 9 shows an example of using PInvoke to access the logged-on user's username directly from a Silverlight application.

The PInvoke class shown in Figure 9 uses the DllImport attribute (located in the System.Runtime.InteropServices namespace) to reference Advapi32.dll, which is part of the Windows OS. Advapi32.dll contains a method named GetUserName, which can retrieve the logged-on user's username directly from the OS without having to pass the username into the Silverlight application using the object tag's initParams parameter or call an ASMX or Windows Communication Foundation (WCF) service to get it. The GetUserName method is marked with the extern keyword since it is implemented outside of the Silverlight framework.

Once the GetUserName method is marked with the DllImport attribute, it can be called directly from a Silverlight application. The example in Figure 9 creates a StringBuilder object with a size of 64 and passes it into the GetUserName method. Once the method is called, the username can be retrieved directly from the StringBuilder. More sophisticated PInvoke techniques can be used to add to LOB applications advanced functionality not possible with earlier versions of Silverlight. Visit www.pinvoke.net for a list of PInvoke APIs that can be called.

public partial class pInvoke : Page
{
    public pInvoke()
    {
    InitializeComponent();
    }

[DllImport("Advapi32.dll")]
    static extern bool GetUserName(StringBuilder lpBuffer, ref int nSize);
    
private void button1_Click(object sender, RoutedEventArgs e)
    {
    int size = 64;
    StringBuilder sb = new StringBuilder(size);
    GetUserName(sb, ref size);
    UserNameTextBlock.Text = sb.ToString();
    }
}

Running with Elevated Trust in a Browser

Elevated trust is restricted to OOB applications in Silverlight 4. Fortunately, Silverlight 5 allows applications running in a browser to also benefit from elevated-trust features. To enable in-browser elevated-trust functionality, you'll need to perform a few extra steps, though. Once completed, the steps allow multiple Silverlight applications within an organization to run in a browser with elevated-trust functionality.

To get started, first ensure that elevated trust has been granted by using the OOB settings shown earlier in Figure 8. Next, go to the Silverlight project's Properties and check the Require elevated trust when running in-browser check box.

Note: Enabling this setting will allow the application to run in-browser with elevated trust on the localhost/127.0.0.1 domain by default without doing any extra work. The localhost domain is the only domain that automatically allows elevated-trust in-browser applications to run correctly, though. To verify that the application is working properly, run the generated test page in the Silverlight project's bin folder using the file:// protocol instead of http://. If you haven't performed all the necessary steps outlined next, the elevated-trust features will not work correctly.

Two additional steps need to be performed to allow elevated-trust functionality to run in-browser: adding a registry key and signing the .xap file. To add the registry key, run regedit.exe at the command prompt and add a DWORD key named AllowElevatedTrustAppsInBrowser to one of the following registry locations:

  • for x86: HKEY_LOCAL_MACHINE\Software\Microsoft\Silverlight\
  • for x64: HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Silverlight\

The AllowElevatedTrustAppsInBrowser key must be set to a value of 1, as shown in Figure 10. Although this step can certainly be performed manually on a user's machine, many organizations push out this type of change through an enterprise group policy.

Figure 10: Adding the AllowElevatedTrustAppsInBrowser key into the registry to support in-browser elevated-trust functionality
Figure 10: Adding the AllowElevatedTrustAppsInBrowser key into the registry to support in-browser elevated-trust functionality

Once the registry key is added, you'll also need to sign your .xap file. This can be done by right-clicking on the Silverlight project in Visual Studio, going to the Properties window, and selecting the Signing tab. The Signing tab has a Sign the Xap File check box that needs to be selected. If you have an existing code-signing certificate, you can select it from the appropriate certificate store, or you can select it from a file. If you don't have a code-signing certificate available, you can create a test certificate by clicking the Create Test Certificate button shown in Figure 11.

Figure 11: The Signing tab in the Properties window of a Silverlight project
Figure 11: The Signing tab in the Properties window of a Silverlight project

After you've clicked the Create Test Certificate button, you'll be prompted to enter a password for the test certificate. After you enter the password, a test certificate will be created automatically and placed in the Silverlight project.

Once the certificate is ready, you'll need to install it in the Trusted Publishers store (and possibly the Trusted Root Certification Authorities store, depending on who issued the certificate). To do so, click the More Details button in the Signing screen (see Figure 11), click the Install Certificate button shown on the certificate window, as in Figure 12, then walk through the wizard to install the certificate into the Trusted Publishers store.

Figure 12: Installing the test certificate into a store
Figure 12: Installing the test certificate into a store

After following these steps, you'll be able to run Silverlight elevated-trust applications directly in the browser. You can find additional details about these steps in the MSDN documentation.

Creating Multiple Windows in OOB Applications

OOB applications with elevated trust enabled can now spawn multiple ad-hoc windows in Silverlight 5. This is useful anytime an application needs to display data in different windows that an end user can arrange. Users can even move the windows to different monitors, if desired.

To create ad-hoc windows, you use the new Window class. Simply create a new Window instance, assign the height and width of the window, set the content that should be displayed, then set the Visibility property to Visible. Figure 13 shows an example of using the Window class:

private void NewWindowButton_Click(object sender, RoutedEventArgs e)
{
    var newWin = new Window
    {
    Height = 400,
    Width = 500,
    Content = new TextBlock { Text = "New Window!" },
    Visibility = System.Windows.Visibility.Visible
    };
}

Figure 14 shows an example of the Window class in action.

Figure 14: Creating an ad-hoc window using the new Window class in elevated-trust OOB applications
Figure 14: Creating an ad-hoc window using the new Window class in elevated-trust OOB applications

Vector Printing

Silverlight 4 introduced printing functionality that allowed screens to be printed using the PrintDocument class. However, bitmaps were used behind the scenes to accomplish this, which led to less-than-desirable results in some situations. Silverlight 5 now defaults to vector printing, which provides better results at a variety of scales. What's great about the new functionality is that you can enable it using the same code you used in Silverlight 4. The main difference is that vector printing will be used by default instead of bitmaps. If you want to print using bitmaps, you can call the PrintDocument's new PrintBitmap method. Figure 15 shows an example of using the PrintDocument class to perform vector printing.

private void Print_Click(object sender, RoutedEventArgs e)
{
    var pd = new PrintDocument();
    pd.PrintPage += new EventHandler(pd_PrintPage);
    pd.EndPrint += new EventHandler(pd_EndPrint);
    pd.Print("DataGrid Print");
}

void pd_EndPrint(object sender, EndPrintEventArgs e)
{
    MessageBox.Show("Printing complete");
}

void pd_PrintPage(object sender, PrintPageEventArgs e)
{
    e.PageVisual = dataGrid1;
}

In the example in Figure 15, the PrintDocument's PrintPage and EndPrint events are wired up to event handlers to handle setting the visual element that should be printed and also to notify the user once the print job is completed. From there, the Print method is called to initiate the vector print job.

A new class named PrinterFallbackSettings is also available that can be used to "provide device specific settings for printers that have vector printing limitations." (See msdn.microsoft.com/en-us/library/system.windows.printing.printerfallbacksettings.aspx.) By using this class, you can force vector printing and adjust the opacity threshold for PostScript printers that have specific limitations. PrinterFallbackSettings can be passed into the PrintDocument class's Print method.

Custom Markup Extensions

If you've ever wanted to write your own custom markup extension, such as your own version of {binding Path=FirstName}, Silverlight 5 provides the functionality you need. By writing a custom markup extension, you can add into bindings custom functionality that previously wasn't possible with Silverlight 4 and earlier.

Custom markup extensions typically derive from a base class named MarkupExtension (located in the System.Windows.Markup namespace) but may also implement the IMarkupExtension interface (located in the System.Xaml namespace). The MarkupExtension base class provides a virtual ProvideValue method that can be overridden. You'll use this method to handle the extension's custom functionality.

Figure 16 shows an example of a custom markup extension that can be used to route a button click event directly to a view model method when using the Model-View-ViewModel (MVVM) pattern. This type of functionality can be performed in several different ways, such as using behaviors/triggers, commanding classes, or other techniques, but the code shown in Figure 16 provides a good example of how you can get started using extensions along with several comments to help explain what the code is doing. You can find a more complete example of invoking methods using a custom markup extension at Mike Taulty's blog (mtaulty.com).

public class CallMethodExtension : MarkupExtension
{
    private object _DataContext;
    private MethodInfo _CalleeMethodInfo;

public string Method { get; set; }
    public object Source { get; set; }

public CallMethodExtension() {}

public override object ProvideValue(IServiceProvider serviceProvider)
    {
    //IProvideValueTarget lets us access the target control
    //where the custom markup extension is applied
    IProvideValueTarget target =
        serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;

    //Locate target event of object (ex: Click event for a Button)
    var targetEventInfo = target.TargetProperty as EventInfo;

    //Detect when target object's DataContext changes so we know
    //the object that we'll be calling (callee) as well as its target method
    ((FrameworkElement)target.TargetObject).DataContextChanged +=
        OnDataContextChanged;

    //Return a delegate that will be invoked once the markup extension is called
    var del = Delegate.CreateDelegate(targetEventInfo.EventHandlerType, this,
        this.GetType().GetMethod("EventMethodProxy", BindingFlags.Public | BindingFlags.Instance));
    return del;
    }

//Proxy event handler for control 
    //For example, for a Button the Click event will be invoked and this
    //will get called
    public void EventMethodProxy(object sender, EventArgs e)
    {
    _CalleeMethodInfo.Invoke(_DataContext, null);
    }

//Detect when DataContext has changed
    private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
    _DataContext = e.NewValue;
    _CalleeMethodInfo = _DataContext.GetType().GetMethod(Method,
        BindingFlags.Public | BindingFlags.Instance);
    }
}

You can see an example of using the CallMethodExtension class in XAML in Figure 17. The namespace of the custom markup extension is registered in the root element, then used to access the CallMethod extension object when the Button control is clicked. Once the extension is defined, its Method and Source properties are set to define the target object and associated method to call. In this example, the AncestorBindingViewModel object's AddPerson method will be called when the Button control is clicked.


    
        
    
    
    

More Power for LOB Apps

Silverlight 5 offers a lot of great features that will enhance LOB application developer productivity. With Silverlight 5's built-in support for implicit data templates, XAML debugging, enhanced elevated privileges for in-browser and OOB applications, vector printing, and custom markup extensions, developers can build robust applications that meet the needs of enterprise customers.

There are many more new features available in Silverlight 5-more than I can cover in a single article. Additional features such as 3D capabilities, multi-column text support, improved text clarity, support for bindings in style setters, UpdateSourceTrigger support, network latency improvements, and more are available. For more information about new features in Silverlight 5, check out Pete Brown's post  for additional details, or view the Silverlight 5 SDK documentation.

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish