Pixata Custom Controls
For Lightswitch

Recent Posts

Popular tags (# posts in brackets)

Anonymous types (3) ASP.NET (5) C# (3) C# tricks and tips (2) Computers (6) Design patterns (3) DomainDataSource (3) Dynamic data (4) Entity framework (3) Entity model framework (5) F# (3) LightSwitch (12) Linq (6) Microsoft (2) MVP (2) MVVM (2) Project Euler (2) RIA services (5) Silverlight (2) SQL Server (4) Unit testing (4) Visual Studio (7) WCF (3) WPF (3)

Gratuitous link to StackExchange




The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Actually, as I'm self-employed, I guess that means that any views I expressed here aren't my own. That's confusing!


Theme modified from one by Tom Watts
C#/F# code styling by Manoli (for posts pre-2016) and Google code prettify (for post from Jan 2016 and beyond)

My rambling thoughts on exploring the .NET framework and related technologies

Please note that this blog has ben retired. Most of the material has been migrated to my new blog at www.pixata.co.uk. Please update your bookmarks to point to the new blog.

Why a toolbar control?

A month ago, I posted an article showing how to create a custom toolbar for a Lightswitch application. At the time, I thought that this was so easy that there was little point in creating a control extension for it. However, the more I thought about it, the more I realised that whilst it’s very easy for an experienced programmer, it wouldn’t be quite so easy for someone with less experience. Furthermore, easy as it was, it still requires you to build the toolbar yourself and write the code.

This niggled me enough to have a go at creating a control extension to implement the toolbar. Along the way I learned some new Lightswitch tricks, and ended up with a control that’s even easier to use than writing your own!

You’ll need the latest version (1.15, published today on the Visual Studio Gallery) of the control extension to follow along. Imagine we have a Lightswitch application that maintains contact details for ferrets (as you do!). We have a list and details screen that displays the ferrets’ information, and want to add a toolbar above the details side to allow the user to change the selected ferret’s name. This is a contrived example, but was the best I could think up on the spur of the moment and with little sleep! For a more realistic example of why you might want a toolbar, see my previous blog post.

Here’s a screen shot of what we’re aiming for...

A static toolbar in action

Regular readers will recognise the dear elephant that has graced this blog several times. The other icons come from my usual source, www.findicons.com, although I recently discovered some great free icons at www.proicons.com. One of the good things about that site is that the icons are organised into themes, rather than being a random collection of individual icons like www.findicons.com. Anyway, you can see that the toolbar above has five buttons, three with just an image, one with an image and text, and one with just text. The Pixata Static Toolbar control allows you to choose how your button will look (including completely restyling it if you want, see later).

Using the toolbar control

To use the control, click the “Add A Data Item” button on the Lightswitch designer window, and add a new Local Property. As with all the static controls, this is merely to get around the Lightswitch limitation of requiring all controls to be bound to something, so you can leave it as a string (uncheck the “Is Required” checkbox) and name it anything you like. I tend to call mine StaticProperty, as it helps me remember what it is when looking at the designer, but you can call it anything you like.

Drag this property onto the designer wherever you want the toolbar to appear, and change the control type to Pixata Static Toolbar control...

Choosing the Pixata Static Toolbar control

Setting the button properties

Have a look in the Properties panel. The first three properties apply to all buttons in the toolbar. The “Image width” and “Image height” properties set the size of the images to be displayed on the buttons. For simplicity (and to make the toolbar look nicer), you have to set the one width and one height, and this will be used for every button. Next you can set the margin for the button. The default is “0,0,5,0” which gives 5 pixels space to the right of each button, so they don’t squash right up next to each other. You change this to whatever you like, but the default setting is probably all you’ll ever need.

After that, you’ll see five groups of properties that look like this...

The properties for a button

Unfortunately, I don’t think there is any way to group these visually, but you’ll see that there are five sets of identical properties. The checkbox specifies if the button is displayed or not. The toolbar allows you up to five buttons, but also allows you less by clearing the checkboxes. If you want more than five buttons in a toolbar, just add two of them.

The link below the checkbox allows you to select the image that will be used for the button. The text for the button is shown next. If you just want an image on the button (like in the 1st, 3rd and 5th buttons in the screen shot at the top of this post), then leave this property blank. If you choose an image and enter text, you’ll end up with both, like the 2nd button in the screen shot earlier. If you just enter text and don’t choose an image, then you’ll end up with a text-only button, like the 4th button above. This last option isn’t that exciting, as you can do this in Lightswitch alone.

The tooltip is the text that will be displayed when your mouse hovers over the button. In the screen shot earlier, my mouse (which you can’t see) was hovering over the 2nd button, and the tooltip text is displayed.

The “Tag text” property allows you to set the tag of the button to a string. The purpose of this will be explained below.

Handling the button click event

The only other thing you need to do is to handle the event when a button is clicked. This is the only place you need to write code to use this control. Click the “Write code” button in the screen designer, and choose the ScreenName_InitializeDataWorkspace event. The first thing you need to do is add the following line at the top of the file...

using PixataCustomControls.Presentation.Controls;

Then add the following lines inside the event handler that was created for you...

partial void FerretsListDetail_InitializeDataWorkspace(List<IDataService> saveChangesTo) {
  var toolbar1 = this.FindControl("FerretToolbar");
  toolbar1.ControlAvailable += (S, E) => {
    StaticToolbar stb = ((StaticToolbar)E.Control);
    stb.ButtonClick += new System.EventHandler<StaticToolbarEventArgs>(FerretToolbar_BtnClick);

My toolbar is called FerretToolbar, so unless you’ve chosen the same name (welcome fellow ferret fan!), you’ll need to change that to match what you chose. By default, Lightswitch will name it after your static property, but you can change this to something more meaningful.

When the ControlAvailable event fires, the code above grabs the toolbar control (which I’ve stored in a local variable called stb), and then subscribes to the ButtonClick event, which will be fired whenever someone clicks one of the toolbar buttons. To make life easier, I only added one event instead of five.

All you need now is the event handler. Here is a sample...

void FerretToolbar_BtnClick(object sender, StaticToolbarEventArgs e) {
  FerretsSet.SelectedItem.Name = e.TagText;

This simple example simply updates the selected ferret’s name to the tag text of the button that was clicked. If your application requires similar behaviour for each button, then using the tag text is a great way to simplify the code. This is similar to the way I inserted standard text in the previous blog post. If you don’t set the tag text, then this will set the name to the empty string.

If you want to have your buttons do distinct things, then this isn’t necessarily the best way to go, as the tag text doesn’t give enough flexibility. In this case, you can just check which button was clicked, and branch appropriately. The ButtonClick event takes a StaticToolbarEventArgs object, that contains the tag text (as shown above), as well as the number of the button. Note that the buttons are numbered one to five and NOT zero to four, as I thought that was too confusing for the general user.

Here is a sample of how to handle this case...

void FerretToolbar_BtnClick(object sender, StaticToolbarEventArgs e) {
  switch (e.ButtonNumber) {
    case 1:
    case 2:

I’ve only shown two cases here to save some space, but it would work the same if you use more buttons.

Modifying the buttons as much as you like

I know that there are people out there who will immediately ask me if they can get hold of the individual buttons, so they can customise them like crazy! Well, I’m one step ahead of you! The control exposes an indexer, which allows you to get the actual buttons on the toolbar. Once you have the toolbar itself (as I did in the FerretsListDetail_InitializeDataWorkspace event handler earlier), you can just do this...

stb[1].Content = "New Text For Button #1";

This rather pointless example shows you how to set the Content for the button to a plain string. As mentioned above, you can do this from the Properties panel without needing code, or you can use a regular Lightswitch button (generated when you drag a method onto the designer surface). However, the point here is that stb[1] is the actual button, so you can do anything to it that you could do to a normal button, including replacing the Content with something of your own invention. I can’t think of any suitably weird example, so I’ll leave that to you dear reader!

Note again that the buttons are numbered from one to five, so if you attempt to access button zero, you will get an IndexOutOfRangeException exception.

One small niggle

One thing I found was that if you want a toolbar with more than five buttons, and you use two of my static toolbar controls next to each other, Lightswitch helpfully adds three pixels of blank space between them. It does this to all controls, so they don’t get all squashed up, but in this case, it is not desirable. I contemplated hacking around to try and remove these three pixels, but decided it wasn’t worth the effort, especially as most toolbars will not have more than five buttons that need to be together. You generally find that toolbars have their buttons in smaller groups, with a vertical divider between the groups. You can do this easily by using several static toolbar controls, and separating them with the Pixata Vertical Divider control. You’ll need to add something between the divider and the next toolbar, so that Lightswitch adds its three pixels. The easiest way to do this is use a Pixata Spacer Control, with the width set to zero.. .

The 1st and 4th controls in that Columns Layout are two static toolbars. The second control is the vertical divider (width set to 1), and the 3rd control is a spacer whose width is zero.

The result of this looks like this...

I hope you find this new control useful. As usual, if you have any comments or questions, please leave them on the Visual Studio Gallery page.

Update 24th Sept ‘12

For those using VB.NET, here is a sample of an entire screen code that does pretty much the same as the code above.

Imports PixataCustomControls.Presentation.Controls

Namespace LightSwitchApplication

Public Class Customers

Private Sub Customers_InitializeDataWorkspace(saveChangesTo As System.Collections.Generic.List(Of Microsoft.LightSwitch.IDataService))
  AddHandler Me.FindControl("FerretToolbar").ControlAvailable, AddressOf FerretToolbar_ControlAvailable
End Sub

Private Sub FerretToolbar_ControlAvailable(sender As Object, e As ControlAvailableEventArgs)
  Dim FerretToolbar As StaticToolbar = TryCast(e.Control, StaticToolbar)
  AddHandler FerretToolbar.ButtonClick, AddressOf FerretToolbar_ButtonClick
  ' Set properties here if you like
End Sub

Private Sub FerretToolbar_ButtonClick(sender As Object, e As StaticToolbarEventArgs)
  Customers1.SelectedItem.Name = e.TagText
End Sub

End Class

End Namespace
Sunday, 03 June 2012 14:48:00 (GMT Daylight Time, UTC+01:00)