Dave's Silverlight Dashboards and gauges

Welcome

There are 14 dials and gauges in the Codeplex.Dashboarding library. This tutorial will show you how to embed the Silverlight guages and dials into your own silverlight applications.

Get the latest version of the controls from the Codeplex project David's Silverlight Dashboards.

Before we start here is a little gratuitous eye-candy to show you where we are going :-) (Hover over a control to see the control name)



The above example shows the following controls:

  • Dial360
  • DecadeVuMeter
  • RoundLed
  • TickCross
  • PerformanceMonitor
  • FiveStarRanking
  • SixteenSegmentLed
  • Odometer
  • Thermometer
  • ProgressBar

New dials and gauges will be added as time goes by, so check back here ocassionally or visit the Codeplex project to see whats new.

Getting started

Before we wade in to the XAML for declaring dashboard controls, we need to look at the requirements for creating a project using them. The controls are declared in an assembly named Codeplex.Dashboarding.dll you can find the assembly in the xap file shiped with the example .NET solution (rename.xap to .zip and extract).

As time goes by we may move the assembly into an easier to find location! Once you have the assembly from the xap file, add it as a reference to your Silverlight application

To add controls to a XAML file you need to create a namespace, to make the samples consistant we will use the following:

xmlns:db="clr-namespace:Codeplex.Dashboarding;assembly=Codeplex.Dashboarding"

The namespace with the prefix db contains all dashboard controls.

If you prefer using Expression Blend over hacking XAML then Blend will add a namespace declaration automatically for the Codeplex.Dashboarding namespace when you drag a control on to the design surface.

First steps

Once you have added the reference to Codeplex.Dashboarding to your project and added the two namespace declarations to the top of a control try declaring a single dial ( <db:Dial360/>) and see what happens:

            <UserControl x:Class="SilverlightApplication.SingleGuages.FirstStep"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                xmlns:db="clr-namespace:Codeplex.Dashboarding;assembly=Codeplex.Dashboarding"
                    class="kwrd">>
                <Grid x:Name="LayoutRoot" Background="Transparent">
                    <db:Dial360 />
                </Grid>
            </UserControl>

Quite unsurprisingly you get a single dial with the default color and no value set. We can set a value two ways, using the value attribute in XAML or by setting the Value property in the code behind. The value should be in the range 0..100 for now, in a subsequent release we will more add Minimum, Maximum properties to allow any range to be set..

In markup the value can be set as

            <UserControl x:Class="SilverlightApplication.SingleGuages.SecondStep"
               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                xmlns:db="clr-namespace:Codeplex.Dashboarding;assembly=Codeplex.Dashboarding"
                    class="kwrd">>
                <Grid x:Name="LayoutRoot" Background="Transparent">
                    <db:Dial360 Value="66" />
                </Grid>
            </UserControl>

Doing this in the code behind is hardly difficult (except this time we added an x:Name attribute to the dial)

                 public partial class ThirdStep : UserControl
                    {
                        public ThirdStep()
                        {
                            InitializeComponent();
                            Loaded += new RoutedEventHandler(IamLoaded);
                        }

                        void IamLoaded(object sender, RoutedEventArgs e)
                        {
                            Random random = new Random();
                            _dial.Value = random.Next(100);
                        }
                    }

So far we have set the value for the gauge directy in markup and then in code. The final appreach to setting the value is data binding. In the next and final demo we data bind the value property to the MilesPerHour property of a Car class.

I don't know the Car class says about its author, but the only interesting item about a car appears to be how fast it is going :-)

             public class Car
            {
                public double MilesPerHour { get; set; }
            }

Next we need to crate a new control in mark up and declarativly bind the Value property to the cars MilesPerHour property

            <UserControl x:Class="SilverlightApplication.SingleGuages.FourthStep"
               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
                xmlns:db="clr-namespace:Codeplex.Dashboarding;assembly=Codeplex.Dashboarding"
                >
                <Grid x:Name="LayoutRoot" Background="Transparent">
                    <db:Dial360 x:Name="_dial"  Value="{Binding MilesPerHour, Mode=OneWay}"  />
                </Grid>
            </UserControl>

Finally in our code behind we set the controls DataContext to an instance of a new car.

             Car porsche = new Car { MilesPerHour = 99 };
             _dial.DataContext = porsche;
             
et viola! (Which is a French expression - I believe - about musical instruments)

Minimum and Maximum values

All of the examples so far have used the default minimum and maximum value range of 0 <= n <= 100, which if fine for some cases not so for others. The base Dashboard class supports the properties Minimum and Maximum which allow you to specify the range of acceptable values. It's very simple to use:

        <db:Dial180 
            Minimum="-10" 
            Maximum="10" 
            Value="-7" 
        />
        

As usual we only show thw markup for the first one, the second is set to 2 and the third to 7.

Two way data binding

Previously we created a quick and dirty car class to show one way data binding. Before we can show two way binding we need to equip the car class for the 21st century and ake it a dependancy object.

        /// <summary>
        /// Class representing a car  and its velocity
        /// </summary>
        public class Car : DependencyObject, INotifyPropertyChanged
        {
            /// <summary>
            /// raised when a property changed
            /// </summary>
            public event PropertyChangedEventHandler PropertyChanged;

            /// <summary>
            /// dependancy property for MilesPerHour
            /// </summary>
            public static readonly DependencyProperty MilesPerHourProperty =
                DependencyProperty.Register("MilesPerHour",
                                            typeof(double), typeof(Car),
                                            new PropertyMetadata(new PropertyChangedCallback(MilesPerHourPropertyChanged)));

            /// <summary>
            /// Speed in Miles per hour 
            /// </summary>
            public double MilesPerHour
            {
                get { return (double)GetValue(MilesPerHourProperty); }
                set { SetValue(MilesPerHourProperty, value); }
            }

            /// <summary>
            /// Dependancy property changed, raise the PropertyChanged event
            /// </summary>
            /// <param name="dependancy"></param>
            /// <param name="args"></param>
            private static void MilesPerHourPropertyChanged(DependencyObject dependancy, DependencyPropertyChangedEventArgs args)
            {
                Car instance = dependancy as Car;
                if (instance != null)
                {
                    instance.OnPropertyChanged("MilesPerHour");
                }
            }

            /// <summary>
            /// Property has changed lets inform the waiting world
            /// </summary>
            /// <param name="prop"></param>
            private void OnPropertyChanged(string prop)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(prop));
                }
            }
        }

In our next example we are going to create an instance of a car in the code behind and initialize the controls DataContext to that value.

The markup below shows a slider and a Dashboard cmponent (FiveStarRanking) bound to the same property of the DataContext in a TwoWay mode. Move the slider and you will see the FiveStarRanking update to show the new value

        <StackPanel Orientation="Vertical">
            <db:FiveStarRanking Value="{Binding MilesPerHour, Mode=TwoWay}"/>
            <Slider Value="{Binding MilesPerHour, Mode=TwoWay}" Minimum="0" Maximum="100"  Width="100" />
        </StackPanel>
        

Accepting user input

Traditionally executive dashboard have presented information and not taken input. Increasingly however dashboards are becoming more about control than presentation, users want to move the needle of a gauge to increase the budget of a department.

Starting with build 007 of the Dashboard library certain compoents are capable of being set as well as showing data.

These controls present the IsBidirectional property which allows the user to specify that the control takes input. In the example below grab and move the triangular shaped handle and see that the sider updates to reflect the new value

    <db:FiveStarRanking Value="{Binding MilesPerHour, Mode=TwoWay}" IsBidirectional="True"/>
    <Slider Minimum="0" Maximum="100" Value="{Binding MilesPerHour, Mode=TwoWay}" ></Slider>
       

You can see all of the Bidirectional controls in action on this page

That's the end of this general overview of the Codeplex.Dashboarding assembly. Please select a control from the list on the left to get a more detailed description.

Welcome page

Controls

  • DecadeVuMeter
  • Dial180
  • Dial360
  • DiamondSlider
  • FiveStarRanking
  • MatrixLedMarquee
  • Odometer
  • PerformanceMonitor
  • PlainThermometer
  • ProgressBar
  • RoundLed
  • SixteenSegmentLED
  • TickCross
  • WallThermometer

Bits and pieces

  • Bidirectional operation
  • Contacts and pages
  • Matrix font editor
Designed by Free CSS Templates, Thanks to Dubai Villas