How to manage Control States in Silverlight Applications

In 2006 I developed a small piece of code in order to use a declarative control state handling in WinForm Applications. Three years later (2009) I thought declarative control state handling should be standard in Silverlight – but I failed. So I decided to migrate that piece of code to the new Silverlight plattform.

Imagine you have a really big application – How would you ensure the control state of every control? In former times this had been done in endless “if – then – else” horror code blocks. That time is history now. A better solution is to use a configuration file and define rules to enable/disable and visible/collapse controls.

Before you read: Here’s an example application.

Here’s the configuration file for the example:

<?xml version="1.0" encoding="utf-8"?>
<uipConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:xsd="http://www.w3.org/2001/XMLSchema&quot;>
<StateSections>

<section name="Page">
<Elements>
<add key="txtAlwaysVisible" state="True"/>
<add key="txtVisibleHidden" check="IsVisible" changeVisibility="true"/>
<add key="radEnabled" check="IsRadioButtonEnabled" />
<add key="radAdmin" roles="Admin" />
<add key="radEditor" roles="Editor" />
<add key="radBoth" roles="Admin, Editor" />
</Elements>
</section>

</StateSections>
</uipConfig>

As you can see the uipConfig file is devided in Sections. A Section is a logical component that contains controls. In our example the Section is defined as the Silverlight Page. In the every section all controls that are interessting for us have a key that is used to define the rules.

Here are the allowed attributes:

Attribute Description
state Can be set to true / false or can be left empty. If a state has been set, all other checks will be ignored.
roles It’s a comma separated list with roles, the current principal must belong to. If the current principal does not belong to the role, the control will be disabled.
check It’s a comma separated list with check routines that tells the State Manager if the control has to be disabled or enabled. Such a check routine can be implemented in a controller class or within the Page itself – and it’s more or less a property that returns true or false.
changeVisibility This flag defines, if the visibility of the control shall be changed. If this flag has not been defined, the enabled/disabled state is used.

All you have to do is to make the ControlStateExtender available to your silverlight application. Therefore you have to place the reference in your UserControl element of your page.

<UserControl x:Class="SilverlightControlState.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
xmlns:state="clr-namespace:SilverlightControlState.ControlState;assembly=SilverlightControlState"

After that you can add the attribute sate:ControlStateExtender.ControlKey to any of your controls.

Example:

<TextBlock state:ControlStateExtender.ControlKey="Page, txtVisibleHidden"
</TextBlock>

The first word defines the section, the second the key of the control within the section. Now – what do you have to change in code?

That’s pretty easy and also straight forward. You have to add a private readonly ControlStateExtender to your page. This object handles the state of your controls. Furthermore you have to initialize the ControlStateExtender object after the call of InitializeComponent().

public partial class Page : UserControl
{
    private readonly ControlStateExtender cse = ControlStateExtender.GetExtender("Page");
    
    /// <summary> Constructor </summary>
    public Page()
    {
        InitializeComponent();
        cse.Initialize(this);
    }

Now you can define the control state rules in your application.
Example:

#region Control State Rules

public bool IsVisible
{
    get
    {
        return radVisible.IsChecked.Value;
    }
}

private bool disableRadioButtons = false;
public bool IsRadioButtonEnabled
{
    get
    {
        return !disableRadioButtons;
    }
}

#endregion

The control state rules (business rules) will be invoked by the ControlStateManager when the Refresh() method is called. So, any time, you expect the control states to be changed you have to call the Refresh() method of the ControlStateManager to re-validate the rules.

Example:

#region Handler that refrehes the control state

private void OnRadChecked(object sender, RoutedEventArgs e)
{
    cse.Refresh();
}

private void OnEnableDisableClick(object sender, RoutedEventArgs e)
{
    disableRadioButtons = !disableRadioButtons;
    cse.Refresh();
}

private void SetAsEditor(object sender, RoutedEventArgs e)
{
    CurrentPrincipal.Principal = new MyEditorPrincipal();
    cse.Refresh();
}

private void SetAsAdmin(object sender, RoutedEventArgs e)
{
    CurrentPrincipal.Principal = new MyAdminPrincipal();
    cse.Refresh();
}

#endregion

If you write your own application, don’t forget to embedd the uiStates.config in your silverlight application. To to this, set the Build Acction to “Embedded Resource” for the uiStates.config.
uiStates

Last but not least I want to say thanks for the ReaderWriterLock Re-Implementation of Vance Morrison. As an additional goodie the code uses a Cache Implementation to store the method, properties and config sections. This Cache Implementation is not dependend on the ControlStateExtender and can be used everywhere in your application.

Here’s the complete source code of the ControlStateExtender example application.

Hope you enjoy it.
Cheers

- Gerhard

kick it on DotNetKicks.com

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 106 other followers

%d bloggers like this: