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

Archives


Categories


Disclaimer

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!


Acknowledgments

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

# Monday, 25 January 2016

As my regular reader will know, I love anything shiny and new, and so was intrigued when I came across F#. When I was an undergraduate (some 25 years ago, ulp!), I played around with Prolog, and enjoyed the different approach to programming it offered.

However, as my time in front of the computer is at a premium, my F# learning started off with reading books and blog posts late away from the computer, usually last thing at night, and not actually doing any coding. Like most C# developers who come across F#, my initial reaction (other than “Hey, that’s shiny and new, I want to learn it!”) was “Why?” If you search around for terms like “why f#” and “c# vs f#” you’ll find that this is a very common question.

The problem is that the answers aren’t very good. Well, let’s be blunt, there are a lot of lies out there. Now before anyone starts flaming me in the comments (not that anyone ever reads this blog, much less leaves comments), I should point out that the criticisms that I can feel coming are not aimed at the F# community in general, nor are they aimed at F# itself. It’s the way people try to sell it that annoys me. I’ve been brooding over them for months, and have written this blog post in my head many times. I feel less strongly about it than I used to, so this will probably be a watered-down version of the original rant.

Wild exaggerations

As an example, I recently came across the following quote in an F# book… “No other .NET language is as easy to use and as flexible as F#!” (the exclamation mark was part of the quote, not my addition). Now this sort of comment really annoys me. Firstly, it’s completely unsubstantiated, and secondly, it’s totally subjective. Any language is easy to use and flexible if you learn it well enough. OK, maybe not any, Lisp is clearly only for weirdos (like my brother who loves it!), but let’s not go down that route. F# is not inherently easier than any other languages, and in some ways is quite a bit harder to learn, as it involves a significant shift in thinking to do it properly. Comments like that make me feel they are trying to cover something up, and have a negative effect – apart from the obvious feelings of antipathy towards the author.

Another idiocy was included a popular book by very well-respected member of the F# community, who attempted to sell F# by showing some pseudo-C# code, claiming that you can’t do this in C#, but you can in F#. Hey, isn’t F# great? My immediate reaction was to shout at the book “You can do that in C# if you bother to write it properly!” He had deliberately lied about what you can do in C# to try and show how F# is so much better. Given that the book was aimed at C# developers who wanted to learn F#, I thought this was a pretty dumb thing to do. A lot of the book went like this, and I shouted at it a lot!

The blogs weren’t any better. I read no end of them, telling me all the reasons why F# was better, and remained unconvinced. This was partly because some of the reasons given were simply not F# at all. For example, one of the most common reasons given for why we should all be using F# is F# Interactive. The point they all ignored is that FSI is not F#, it’s a tool that Microsoft happened to have implemented for F#, and hadn’t implemented for C#. As it happens, Visual Studio 2015 now includes a C# Interactive window, so this supposed benefit is no longer valid anyway. I doubt they’ll stop their bleating though.

Type inference

Another reason given for F# being the best thing since sliced bread is the type inference. Well, despite having struggled to understand the benefits, I’m still very doubtful about this one. Yes it makes the code shorter, but it makes it a whole lot harder to read. When I look at a piece of C#, I can see straight way the variable types and the method return types, so I can concentrate my mind on hat the code is doing. I can’t do that in F#. Having said that, when writing F#, the type inference is a joy, as you can concentrate on what the code is doing, and ignore the technicalities. It’s a two-edged sword, and not an undiluted benefit.

Well, it's so clean, sir!

The final claim I want to address is that F# code is so much cleaner than C#. Well, there is something in that, but clean isn’t necessarily better. I suspect most people will recognise the following snippet from what is arguably one of the funniest moments in comedy...

Customer (John Cleese): It's not much of a cheese shop, is it?
Owner (Michael Palin): Finest in the district sir!
C: (annoyed) Explain the logic underlying that conclusion, please.
O: Well, it's so clean, sir!
C: It's certainly uncontaminated by cheese.

Being clean can also be a disadvantage.

Apart from the specification of types (see above for why I’m not convinced that this is a bad thing), the only other part of C# that’s not clean is the fact that you have brackets knocking around, whereas F# is totally devoid of them. Again, this might make the code slightly shorter, but has its disadvantages. For example, if I have a few lines of C# code, and want to surround them with an “if” statement, I can just add the “if” statement on the line before the block, and a closing brace on the line after, then reformat the code, and all the indenting is done for me. I know the insertion will be right, as it can’t fail. If I want to do the same in F#, I have to concentrate a lot harder on adding the right amount of extra indentation to the lines I want inside the “if” block. It’s significantly more likely to go wrong.

If the few extra lines added by braces really bother you that much, go buy a bigger monitor! I can see around 70 lines of code on mine, so the few extra lines added by the braces rarely cause me any problems.

To make it even worse, when comparing evil C# code against the pure and sainted F# equivalent, they somehow always manage to stick as much extra code into the C# version as they can. F# snippets would be a method, and nothing else. The equivalent C# snippet would be a whole class, including usings. This is a false comparison.

I |> Red heart F#

By this point, you probably think I hate F#. Well, it’s not true. My point here is not anything against F#, it’s against the lies and exaggerations bandied around by the F# fan boys. I probably would have given up on F# in annoyance at these lies (as I suspect many, many others have done) were it not for the fact that I am fascinated my shiny new things. I decided to carry on anyway.

Thankfully, I discovered Project Euler. For those who haven’t discovered this wonderful site yet, it’s an ever-growing collection of mathematical and computer programming problems. Apart from my inherent love of such things, this was the perfect opportunity to learn F#.

Now you can use PE by simply solving the problems, entering your answer to check you got it right, and carrying on to the next one. I decided not to do that. I solved the problem, then went back and tried to find ways of improving my code. I posted my samples up for code review, and played around with the suggestions I got. I searched around for other people’s solutions (only after I had already solved it myself) to see if I could find better code. When I did, I copied it, played with it and made sure I understood it.

In time (not much actually), an amazing thing happened. I got really excited about F#! When you get into it, it’s a really nice language to use. I’m still not convinced that there are many major benefits over C# for my line of business (pull data from a database, display it on a window, wait for the user to make changes, save the data back to the database, etc), but for the sort of work that I would love to do, like machine learning, data analysis and so on, it seems wonderful. Sadly, I reckon my use of it will be largely recreational, unless I can find some justification for using it in my day job.

If I get around to it, I’ll post some of my Project Euler code here, so others can laugh at it, and feel better about their own code.

F#
Monday, 25 January 2016 20:00:00 (GMT Standard Time, UTC+00:00)
# Thursday, 18 June 2015

Having blogged recently about a stupid error message, I came across another one! Microsoft much employ people to craft these, they just couldn’t be there by accident. I reckon they are put there to amuse developers, and distract them from the fact that the software is misbehaving!

Anyway, I was using the SQL Server Import and Export Wizard, and it threw up the following error message:

Error 0xc004706b: Data Flow Task 3: "Destination 14 - EntityHistory" failed validation and returned validation status "VS_ISBROKEN"

I just love that last bit!

Thursday, 18 June 2015 21:16:00 (GMT Daylight Time, UTC+01:00)

And I’ve seen a few!

I was just trying to back up an SQL database, and got this truly wonderful error message...

Not much you can say to that is there?

Wednesday, 18 March 2015 03:14:00 (GMT Standard Time, UTC+00:00)
# Tuesday, 13 January 2015

My regular reader may remember that I wrote a while ago that my computer laughs at me. Well, it lies to me as well.

Bored of the usual methods of inflicting torture upon myself, I thought I would upgrade SQL Server 2008 R2 to SQL Server 2014 (stop laughing at the back!), because, erm, well it seemed like a good idea at the time.

First problem was that in order to upgrade, I had to apply service pack 2 to my existing SQL Server 2008 R2 installation. Why? No idea. I would have thought that if I were about to upgrade, it should have all of the later goodness in the upgrade, but who am I to question the ways of the wise?

So, I downloaded SP2 and set it going. Part way through, I got an unhandled .NET exception (nice one Microsoft, very professional), and when I clicked Quit, it continued with the installation! Still, as it seemed to work, I didn’t complain, but I was a bit annoyed that it lied to me. Computers aren’t supposed to do that.

Once I had SQL Server 2014 installed, I happened to notice that SQL Server 2008 R2 was still installed. Huh, I thought we upgraded to 2014? Shouldn't it have uninstalled 2008 R2? Well, I would have thought so too, but that just shows how much we know eh? If you have Visual Studio 2013 installed, you may well have SQL Server 2012 installed as well! Good job disk space is cheap nowadays.

Having asked about this in an SQL Server forum, I was told it was safe to uninstall anything related to SQL Server 2008 R2. Whilst doing so, I came across one component that gave me a message saying that SSMS 2014 depended on it, and if I uninstalled it, that would stop working. I clicked "No" to say I didn't want to uninstall this component, but it uninstalled it anyway! Didn't seem to matter, as SQL Server worked fine afterwards, so it just shows what liars they are!

I’m very disillusioned. No wonder the world is sinking into moral decay if you can’t even rely on your computer to tell you the truth!

Tuesday, 13 January 2015 20:49:00 (GMT Standard Time, UTC+00:00)

As my regular reader will know, when Lightswitch came out, I was quickly hooked. Like many people, I saw an answer to the hassle of creating n-tier desktop applications. It was a dream. Development time was slashed, and the few annoyances that there were paled into insignificance compared to the speed of development, and the quality of the end product.

I dived in head-first, and quickly came up against some of the limitations of a first version. That’s not a criticism, it’s more a testimony to the amazing power the first version had, that we could produce real LOB applications, and were frustrated by the missing bits.

Thankfully, Microsoft did a sterling job of adding extensibility points to Lightswitch, and despite the poor documentation (an ongoing feature of Lightswitch that caused a lot of wasted hours), the potential was there to fill in the gaps.

Inspired by early experimenters, like Yann Duran’s excellent Luminous Controls (which I still use in every Lightswitch project), I had a go at producing a custom control for Lightswitch, more for the fun of tinkering than anything else. Having worked out how to get going, I added a few more controls, until the first version of the Pixata Custom Controls For Lightswitch was born. Feeling that I had something that might be of use to others, I added it to the Visual Studio Gallery, and posting about it in the (now extinct) forum. I got so excited when it had 100 downloads!

Spurred on by the great feedback, I added more controls, and the control suite hit the top three for Lightswitch extensions. It varied between the first, second and third places, but has always been in the top three. To date, it’s had over 25,000 downloads, despite that the fact that I haven’t updated the controls for over a year.

Roll on a few years, and the mobile market exploded. Smartphones and tablets gained more power, and were able to browse the web almost as well as their desktop cousins. However, probably due to political more than technical reasons, the manufacturers chose not to support Flash or Silverlight on these devices, leaving Lightswitch out in the cold.

Microsoft, fairly understandably, decided to concentrate their efforts on producing a version of Lightswitch that would support mobile devices. That's where the HTML client came in.

This was fine, except for two huge problems...

1) The HTML client was (and still is from what I can see) woefully short of being ready for the job. It's a good start, but not good enough to create LOB applications. Specifically, despite the massive growth of the mobile market, Microsoft seem to have forgotten that the desktop world still exists, and still accounts of a very significant number of users, especially in the business world. Until the HTML client supports the desktop, it can't be considered ready for serious use.

I have other misgivings about the HTML client, but they are minor in comparison to this one. I know the mobile market is important, but in business-to-business work, which is a significant part of the software development world, you just can’t afford to ignore the desktop.

2) Whilst I don't think we can criticise Microsoft for moving away from Silverlight, which must have been hard for them, having put so much effort into producing a first-class product, what is totally unforgiveable (in my opinion at least, and I know I'm not alone) is the way they just dumped the Silverlight developers without any support. Their support for the more advanced side of Lightswitch was always poor, but when the HTML client came along, Silverlight client developers were just ignored completely. The extensibility forum died a sudden death, with unanswered questions making up the sum total of all posts.

Now, before I get criticised for this, I understand that they have limited resources, and want to concentrate their efforts on the latest and greatest, but many, many developers sunk a large amount of time and energy into Silverlight-related development, and to have all support cut off in an instant was a really dirty trick. I think we can all understand why they don’t want to invest more time in active development, but at least support what’s already there.

The problem became more acute as time went on, and Microsoft were pushing the HTML client with an evangelical fervour. It got to the stage where I knew that if I had a problem, there was little point in posting in a forum, as my post would be swallowed in a sea of HTML-related questions, and wouldn’t be answered by anyone at Microsoft anyway. The only way I could get an support was peer-to-peer support from some of the Lightswitch rock stars.

It came to a head for me recently when, having invested a significant amount of time in developing a complex application, it suddenly stopped working. The only clue I had was the rather generic error message “Cannot communicate with the database” when the application started. It worked fine on my development machine, and the database connections were all correct (I could even change the connection strings in Visual Studio, and run the application against the remote production database, so I know that wasn’t the problem), but the deployed version refused to work.

After struggling to get the attention of any Microsoft support person, I eventually had to give up and rewrite the entire application in WPF and ASP.NET WebAPI2. Surprisingly, it didn’t actually take that long, and left me wondering if Lightswitch is really as RAD as I had thought, once you get away from the basic functionality.

So, I’m left with a sour taste in my mouth, and some deployed Lightswitch applications that I’m terrified to touch, in case they mysteriously stop working as well. I can’t afford to rewrite them from scratch, and know that there is no way I’ll get any support if they stop working. I’m just hoping the customers don’t want any changes.

Sad end to a promising product. I have little interest in investigating the HTML client, as ASP.NET MVC makes it so easy to produce high-quality web sites that work in both desktop and mobile environments, and I can’t see any benefits in Lightswitch for this.

As for the controls? Well, I’ve made them open source, so if anyone wants to develop them further, they can.

Sunday, 14 December 2014 15:01:00 (GMT Standard Time, UTC+00:00)

Last February, I hit a problem where I was trying to implement printing from a Lightswitch screen, and was using what has now become known as the Command Table Pattern, which allows the Lightswitch client to send a command to the server. I was encountering an error with the witty message “A new instance of the EntityObject class cannot be initialized because the ambient IDataWorkspace is not available. Please use the constructor that specifies an EntitySet” which was as clear as mud to me!

I asked about this in the Lightswitch forum, and was greatly helped by the ace Lightswitch insider Justin Anderson, who patiently explained that the problem I was facing was to do with threads, dispatchers and workspaces. This area is one of those that seems to trip up a lot of people when they start digging into Lightswitch, and is very poorly documented. The few articles I have seen are fairly difficult to understand, which only compounds the problem. Thanks to Justin’s help, I got my code working, and got a better understanding of the subject.

Well, a few weeks ago, Steve added a comment to that forum post, as he was having a very similar problem when trying to create a new entity in the Click event handler of my Pixata Static Toolbar control. As I tried to explain what the problem was, I ended up explaining threads, dispatchers and workspaces, as he had hit exactly the same lack of understanding of these that led me to make the post in the first place.

He seemed to like my explanation, so I decided to post it here, as it may help someone else. Let me say in advance that this is not a comprehensive explanation, nor is it totally accurate, because it's a complex subject and I want to try and explain it in a way you'll understand. If any Lightswitch gurus are disgusted at my explanation, please feel free to leave a comment below, or email me Smile

Let’s deal with threads first...

In order to keep the UI responsive, Lightswitch uses two threads (think of two small men inside your PC, each one doing something different, but talking to each other to keep their work in synch). The main thread, let's call him Fred, handles getting data from the server and sending it back again. The other thread, whom we'll call Jim (because Jim is a good name) handles the UI stuff, like making sure the textboxes and comboboxes are drawn on the screen, and contain the right data.

When you do things like typing, choosing from a combobox, etc, you are talking to Jim. When you hit the Save button, this sends a message to Fred. You don't talk to Fred directly like you do to Jim, as Fred is in the background, round the back of your monitor where all the dust and dead flies collect, so when you click the Save button, what really happens is that Jim sends Fred a message saying "Here Fred, this one is for you." When Fred gets the message, he sends the data to the database for you.

The tricky bit is that there are two ways that the user tells Lightswitch what to do. One is through commands, which is how you work when you add a method to the screen (Click the "Add Data Item" button and choose "Method"). This sets up a command that just tells Jim to send a message to Fred, and have Fred do the work. However, if you capture control events, such as a button's Click event, then you are asking Jim to do the work himself, and not get Fred involved at all (he's cleaning up the dead flies while he's nothing better to do).

If that hasn't confused you, then you might have a very general (and rather flippant) idea of how threads work. When you are in a method created as a data item, you are talking to Fred, and Lightswitch creates a DataWorkspace for you. When you are in a control event handler, you are talking to Jim, and there isn't a DataWorkspace around. If you want one, you have to create one.

Aside: As my regular reader will know, I’m a huge fan of Lightswitch, but I do have one big gripe with it, and I think this is the cause of a lot of confusion to new Lightswitch programmers. In the name of good software design, Microsoft used the MVVM pattern when building Lightswitch. This is a familiar pattern to WPF and Silverlight programmers, and (like MVC and MVP before it), allows a clean separation of the business layer from the UI layer.

Now, in a normal (ie WPF or Silverlight application), the view model is in a completely separate file from the view. Thus, command methods are nowhere near control event handlers, which helps keep the separation clear in the mind of the programmer.

However, in Lightswitch, the view model code is in the same file as the screen’s code, meaning that you have methods sitting right next to each other that are actually going to be executing on different threads. I think this is a very bad idea, and seems to be the source of many problems I’ve seen in the forums.

Anyway, gripe over, back to Fred and Jim...

So, if we have two threads, how do they communicate? That’s where dispatchers come in. Dispatchers are a way of having Fred pass work to Jim and vice versa.

Certain tasks need to be done by Fred, as he works with the data. However, if you are inside a control event handler, then you are talking to Jim. So, what you need to do is ask Jim very politely if he will send a message to Fred asking him to do the work. That's where dispatchers come in.

You have two dispatchers, one that passes (ie dispatches) the work to Fred (also known as Main, as he handles the main work), and one that passes the work to Jim (known as Details). Remember, when you're writing code in a control event handler, you're talking to Jim, ie to the Details thread. For example, if you are in a control’s event handler, and you want to create a new entity (as Steve was), you need to pass the job to Fred, meaning that you need to use the Main dispatcher.

In Steve’s case, he didn't actually need a dispatcher, as he could have handled the problem a different way, but if he had, he would have needed the Main dispatcher, as he was already talking to Jim (remember the code was in a control event handler), and he wanted to pass the work to Fred. In such a case, you would do something like this...

    Dispatchers.Main().BeginInvoke(Sub() 
      ' code for Fred to do goes here 
    End Sub)

(Note that Steve was working in Visual Basic.NET, which is why I departed from the norm and didn’t use C# above)

I hope this has helped. If it's any consolation, I think dispatchers are about the most complex bit of Lightswitch there is. Hopefully, if you read the above a few times, it might make some sense. If you run into exceptions to do with threads, chances are you need a dispatcher. There are two ways to work out which one you need to use. The first is good old trial and error! Try one, and if it doesn't work, try the other. This isn't really a good approach, as you don't really get to understand what you're doing. The second approach is to keep reading and trying to understand it until it goes in.

The easiest way to think about it, which will probably work for you in most cases, is that if you are coding in an event control handler, then if you need to dispatch, you use Dispatchers.Main().BeginInvoke. If you are in a data item method, then you will need to dispatch using Me.Details.Dispatcher.BeginInvoke.

Although the DataWorkspace side of this issue is less commonly encountered, I might as well add on a quick overview of that, as it was relevant to the forum post. In simple terms, the DataWorkspace is what you use when dealing with data in Lightswitch, and one is created for you in the view model. However, when working in the screen’s code-behind, you don't have one, which is why the error message shown at the top appears. If you need to access data from an event handler, you’ll probably need to grab your own DataWorkspace.

In my original case (which is the same as Steve’s), I was trying to create a new entity. The entities that Lightswitch creates from your database have a parameterless constructor that uses the ambient DataWorkspace, meaning the one that Lightswitch creates for you (ambient = hanging around counting dead flies, waiting for you to do something that it knows about). If you are in a view model, then this works fine, which is why you generally don’t have to worry about DataWorkspaces, as most of your code should be written in the view model.

However, sometimes you need to do this stuff in event handlers, and you don’t have an ambient DataWorkspace hanging around. In this case, you need to use another entity constructor that takes a DataWorkspace as a parameter. In my case, this meant doing this...

  new InvoiceAction(this.DataWorkspace.MyAppData.InvoiceActions);

All this does is grab hold of a DataWorkspace explicitly, and pass it to the entity’s constructor. Once you know about this, the error message at the start of this article makes more sense, but when you first encounter it, your eyes start to glaze over, and you wonder why there are so many dead flies behind your monitor (Fred has been too busy dealing with your errors to clean them out).

I hope this has been helpful to someone! If you have any comments, or would like to hear how Fred and Jim are getting on, please click the “Comments” link below and let me know.

Thursday, 29 November 2012 15:51:00 (GMT Standard Time, UTC+00:00)
# Tuesday, 30 October 2012

This one amused me...

protected void On_DayLoad(object sender, EventArgs e) {
  Beverage coffee = new Beverage("coffee");
  coffee.Add(Beverage.Sweetener.Sugar);
  coffee.Cream = false;
  Cup mug = new Cup();
  mug.Add(coffee);
  Me.Consume(mug);
  mug.Dispose();
}

Of course, you could argue that the hard-coded string in the Beverage class constructor is bad design, but it’s only a joke eh?

This one is an old one, but I liked the variation of answer...

Question: How many programmers does it take to change a light bulb?

Answer 1: None, it's a hardware issue

Answer 2: A properly designed light bulb object would inherit a Change() method from a generic base Lighting class, so all you'd have to do is send a light bulb change message

Tuesday, 30 October 2012 14:00:00 (GMT Standard Time, UTC+00:00)

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:
      DoButtonOneStuff();
      break;
    case 2:
      DoButtonTwoStuff();
      break;
  }
}

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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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)

As my avid reader will know, I’m a huge fan of Visual Studio Lightswitch, mainly for the ease and speed with which you can get an impressive CRUD (forms over data) application up and running. However, one of the (admittedly few) limitations that I’ve found is that you don’t have as much control over the user interface (UI) as you do in WPF, Silverlight or WinForms applications. Whilst this is generally not a problem, it can sometimes be a issue.

For example, I’m currently working on an application which generates emails and documents at various times. These are based on templates that the user can modify. In order to make life easy for them, I provided an editor in the application, and wanted to give them an easy way of inserting placeholder text that would be replaced when the email or document was generated. In order to add buttons for the placeholder text items, I added several methods to the screen, and dragged these to the designer to create the buttons. As they can modify document templates and email templates, and the latter have both a subject and body, I needed three buttons for every placeholder text in use. The email tab of this screen looked like this...

The Lightswitch application before the custom toolbar

 

As you can see, I placed the two sets of buttons on the right, so they would be easily accessible when typing the template.

The problem with this is that those buttons don’t look very pretty, and they take up quite a bit of screen space. The Documents tab has another set of buttons, for inserting text into the document body. Apart from the looks, this resulted in three almost identical sets of six almost identical screen methods, with the associated problems in maintenance. This bothered me enough to wonder how hard it would be to implement a custom toolbar for Lightswitch, that could be used three times, saving me all that almost identical code.

This turned out to be almost embarrassingly easy, as I will explain with a simple example.

A Simple Example

If you want to follow along, create a new Lightswitch application, and add a table called Customers. Actually, you can add anything you like, this was just the first (moderately sensible) thing that came into my head. The table looks like this...

The Customers table in the Lightswitch designer

Now create a “List and Details Screen” based on this table. At this stage, you can run the application and add some data - don’tcha just LURVE Lightswitch!

In a desperate attempt to think of something useful here, I decided that I wanted a quick way to increase the number of orders recorded for the customer (I know, this would normally come from somewhere else in the database, but bear with me, the point here is to show you how to make a toolbar, not how to write a sensible application!) and to update the date of last contact to the current date and time.

I could do this by adding two methods to the screen, and dragging them onto the designer, but this would look as ugly as the sample I showed above. We want our users to we wowed by the fab UI we gave them, so we’re going to add... elephants! Huh? Bear with me folks, it will all become clear.

To create the toolbar, switch to File View in the Solution Explorer, and find the Client project. Add a folder named UserControls to this project, and add a Silverlight User Control named CustomerToolbar.xaml to the folder. Your Solution Explorer should look something like this...

The solution explorer in Visual Studio when you've added the user control

Aside: Strictly speaking, you don’t need to add the folder, but it’s a good idea to help keep things separate. It’s also worth noting that you don’t need to put your user control in a separate project as many people claim. Unless you’re writing something that will be reused a lot, in which case you’re better of writing an extension, there’s no need to bother with a separate project. As far as I know, the way I have shown will also work with the Express version of Visual Studio, which doesn’t allow extra projects to be added.

Now double-click the CustomerToolbar.xaml file to open it up in the Silverlight designer. There are quite a few ways of creating a toolbar, and I chose to use a set of Button controls inside a StackPanel. My XAML looked like this...

<UserControl x:Class="LightSwitchApplication.UserControls.CustomerToolbar"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             Height="40"
             Width="130">
 
  <StackPanel Orientation="Horizontal">
    <Button Height="40"
            Width="40"
            Margin="0"
            Name="BtnElephant"
            Click="BtnElephant_Click">
      <Image Source="/CustomToolbar.Client;component/Images/elephant.png"
             Height="32"
             Width="32" />
    </Button>
    <Button Height="40"
            Width="40"
            Margin="5,0"
            Name="BtnCoffee"
            Click="BtnCoffee_Click">
      <Image Source="/CustomToolbar.Client;component/Images/rss.png"
             Height="32"
             Width="32" />
    </Button>
    <Button Height="40"
            Width="40"
            Name="BtnBell"
            Click="BtnBell_Click">
      <Image Source="/CustomToolbar.Client;component/Images/alert.png"
             Height="32"
             Width="32" />
    </Button>
  </StackPanel>
</UserControl>

I took the easy approach to adding the images, by creating empty <Image> tags, then clicking the Source property in the Properties panel, clicking the Add button and navigating my way to the PNG file I was using. Visual Studio added the image to my project and set the Build Action to Resource for me. You can do this manually, but why bother?

The designer now looked like this...

The toolbar control in the Visual Studio designer

 

As you can see, we have an elephant, a coffee cup and a bell. All the icons came from www.findicons.com, my usual favourite source of free icons. I picked these three more for their looks than their significance to the task at hand. In a real application, you would want to pick something more meaningful. I also didn’t add tool tips in the XAML above. These are a good idea, and will be added in the final version shown later.

Now switch the Solution Explorer back to Logical View, and double-click the Customers screen you created earlier. We want to add the toolbar to our screen, but as you probably know, version 1 of Lightswitch only allows you to add data-bound items to a screen. We get around this by adding a Local Property to the screen. Click the “Add Data Item…” button at the top of the window, then choose “Local Property,” uncheck the “Is Required” checkbox and give it a name. I tend to use StaticProperty, as this helps me remember what it is, but you can call it anything you like.

Now drag the property onto your screen wherever you want the toolbar to appear. In my case, the screen is a “List and Details” screen, and I want the toolbar above the details section. Once it’s on the screen, change the control type to Custom Control, and in the Properties panel, click the “Change” link. From the window that appears, choose the control...

The window where you can pick the custom control

My screen designer now looked like this...

The Lightswitch screen designer when the custom control has been added

If you run the application now, you’ll see the toolbar looking very smart...

The toolbar on the Lightswitch application

Looks very nice, but it doesn’t to anything yet. We’ll fix that right now.

In order to have the toolbar notify the Lightswitch screen when someone clicks a button, we’ll add some event handlers to the code. Switch to the code-behind file for the control, which in my case is called CustomerToolbar.xaml.cs (you’ll need to be in File View to see this), and change the code to look like this...

using System;
using System.Windows;
using System.Windows.Controls;
 
namespace LightSwitchApplication.UserControls {
  public partial class CustomerToolbar : UserControl {
    public CustomerToolbar() {
      InitializeComponent();
    }
 
    public event EventHandler Elephant;
 
    private void BtnElephant_Click(object sender, RoutedEventArgs e) {
      EventHandler eh = Elephant;
      if (eh != null) {
        eh(this, null);
      }
    }
 
    public event EventHandler Coffee;
 
    private void BtnCoffee_Click(object sender, RoutedEventArgs e) {
      EventHandler eh = Coffee;
      if (eh != null) {
        eh(this, null);
      }
    }
 
    public event EventHandler Bell;
 
    private void BtnBell_Click(object sender, RoutedEventArgs e) {
      EventHandler eh = Bell;
      if (eh != null) {
        eh(this, null);
      }
    }
  }
}

In this case, I’ve added three separate event handlers, one for each button. This is fine if each button does something quite different. In the case of my original application, all the buttons are to do a very similar task, so we can make the code easier, as I’ll show soon. Also, you would probably want to refactor this code to make it slimmer, as there is a lot of almost identical code here. I didn’t bother for this simple example, but will show how this could be done later.

Back in the Lightswitch screen code behind, we simply need to catch the toolbar’s events, and then do whatever we want in response. For the purposes of this demo, I’m going to have the elephant button increase the number of orders for the current customer, and the coffee button set the date last contacted to the current date/time. Here is the complete screen code...

using System;
using System.Collections.Generic;
using LightSwitchApplication.UserControls;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Presentation.Extensions;
 
namespace LightSwitchApplication {
  public partial class CustomersScreen {
    partial void CustomersScreen_InitializeDataWorkspace(List<IDataService> saveChangesTo) {
      this.FindControl("Toolbar").ControlAvailable += (S, E) => {
        ((CustomerToolbar)E.Control).Elephant += new EventHandler(CustomersScreen_Elephant);
        ((CustomerToolbar)E.Control).Coffee += new EventHandler(CustomersScreen_Coffee);
        ((CustomerToolbar)E.Control).Bell += new EventHandler(CustomersScreen_Bell);
      };
    }
 
    void CustomersScreen_Elephant(object sender, EventArgs e) {
      if (CustomersSet.SelectedItem != null) {
        CustomersSet.SelectedItem.NumberOfOrders++;
      }
    }
 
    void CustomersScreen_Coffee(object sender, EventArgs e) {
      if (CustomersSet.SelectedItem != null) {
        CustomersSet.SelectedItem.DateOfLastContact = DateTime.Now;
      }
    }
 
    void CustomersScreen_Bell(object sender, EventArgs e) {
    }
  }
}

As you can see, in the InitializeDataWorkspace event, we grab the toolbar control and set up handlers for the three events. In the event handlers themselves, we set the customer’s properties. I haven’t done anything in the third event handler here, mainly because I couldn’t think of anything useful, given the limited scope of this simple example!

If you run the application now, you’ll find that the elephant and coffee cup buttons work as expected (assuming you expect an elephant to increase the number of orders, and a coffee cup to set today’s date of course!). We have a fully working toolbar, with amazingly little effort.

In this sample, I have added a separate event handler for each button, which is fine when the buttons do quite distinct tasks, as these do. In the original application I showed at the top, the buttons all do a very similar job, so we can improve this control quite a lot...

Tidying Up The Toolbar Code

As I mentioned above, my original case was where I wanted the buttons to insert standard bits of text into controls on the screen. As each button on the toolbar is to do basically the same job, with only a variation in the actual text, we can set up one event in the toolbar control, and use an EventArgs class to pass the text back to the Lightswitch screen.

Imagine the requirements for our sample app have changed, and we now want to set the Customer Name to one of three specified bits of text, depending on which button is pressed.

Switch to File View again, and in the same folder where you created the user control, add a class called CustomerToolbarEventArgs, whose code should look like this...

using System;
 
namespace LightSwitchApplication.UserControls {
  public class CustomerToolbarEventArgs : EventArgs {
    public string Text { get; set; }
  }
}

This class adds a single string property to the standard EventArgs class, which we’ll use to pass the text to be inserted back to the Lightswitch screen.

Change the toolbar control’s code to look like this...

using System;
using System.Windows;
using System.Windows.Controls;
 
namespace LightSwitchApplication.UserControls {
  public partial class CustomerToolbar : UserControl {
    public CustomerToolbar() {
      InitializeComponent();
    }
 
    public event EventHandler<CustomerToolbarEventArgs> BtnClick;
 
    private void FireEvent(string Text) {
      CustomerToolbarEventArgs Ev = new CustomerToolbarEventArgs {
        Text = Text
      };
      EventHandler<CustomerToolbarEventArgs> eh = BtnClick;
      if (eh != null) {
        eh(this, Ev);
      }
    }
 
    private void BtnElephant_Click(object sender, RoutedEventArgs e) {
      FireEvent("I like buns!");
    }
 
    private void BtnCoffee_Click(object sender, RoutedEventArgs e) {
      FireEvent("No sugar please!");
    }
 
    private void BtnBell_Click(object sender, RoutedEventArgs e) {
      FireEvent("Ding dong!");
    }
  }
}

As you can see, we now only have one event handler, which is generic to the CustomerToolbarEventArgs that we created above. The Click event handlers for the three buttons call a common method that sets up an instance of this class, and raises the event.

Now, we can simplify the Lightswitch screen by changing the code to this...

using System;
using System.Collections.Generic;
using LightSwitchApplication.UserControls;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Presentation.Extensions;
 
namespace LightSwitchApplication {
  public partial class CustomersScreen {
    partial void CustomersScreen_InitializeDataWorkspace(List<IDataService> saveChangesTo) {
      this.FindControl("Toolbar").ControlAvailable += (S, E) => {
        ((CustomerToolbar)E.Control).BtnClick += new EventHandler<CustomerToolbarEventArgs>(CustomersScreen_ToolbarButtonClick);
      };
    }
 
    void CustomersScreen_ToolbarButtonClick(object sender, CustomerToolbarEventArgs e) {
      if (CustomersSet.SelectedItem != null) {
        CustomersSet.SelectedItem.CompanyName = e.Text;
      }
    }
  }
}

We only handle the one toolbar event, and just pull the required text from the CustomerToolbarEventArgs.

If you run this now, you’ll find that all three buttons modify the customer name property as expected.

After implementing this idea in my original application, the UI was much neater, as you can see from the screen shot below, and I had reduced the amount of code significantly. More to the point, maintenance was now pretty easy, as I had removed all the duplication.

My original Lightswitch application with the new toolbars in place

Obviously, there is a lot more that can be done here. The more I think about this, the more I realise that it opens up the possibilities of providing a custom UI for a Lightswitch application very easily, without requiring you to write a custom shell. Once again we see how Lightswitch gives you enormous leverage right out of the box, without sacrificing the flexibility that you need.

Thursday, 03 May 2012 11:05:00 (GMT Daylight Time, UTC+01:00)

In yesterday’s blog post, I introduced the Toast control that was added to the Pixata Custom Controls extension for Lightswitch. I mentioned at the end of the post that there were ways of creating much more flexible toasts. In this post, I’ll show you an example of what I meant. With only a little imagination, you should be able to tweak this little toasties to do almost anything!

The limitation with the method I showed yesterday is that it only allows you to set the title and message for the toast, and each of these has to be sent as plain text, without any formatting. In many cases, this is fine, but sometimes you want more control. The important thing to remember is that when you create your own toast, there is nothing to stop you from doing what you like with it before passing it to the ShowToast method. You can create a toast with any properties you like, populate those in your Lightswitch screen’s code-behind, and when you are done, pass it in to ShowToast. You are not limited to passing “new MyToast()” like I showed yesterday.

As an example, I’m going to assume you want to show a pop-up with some RSS feed information in it. I realise that this isn’t very likely from Lightswitch, but it was the first thing that sprang into my mind, partly inspired by finding a nice RSS icon on www.findicons.com. I called the new toast control ToastWithPeanutButter, mainly because I have a very childish sense of humour!

Create the basic control by following the instructions I showed yesterday.

Now, instead of restricting ourselves to two TextBlock controls for the title and message, we are going to do something a little more interesting for the message. Open up the ToastWithPeanutButter.xaml file, and replace the content with the following...

<uc:PixataToastControlBase x:Class="LightSwitchApplication.ToastWithPeanutButter"
                           xmlns:uc="clr-namespace:PixataCustomControls.Presentation.Controls;assembly=PixataCustomControls.Client"
                           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                           mc:Ignorable="d"
                           d:DesignHeight="100"
                           d:DesignWidth="400">
 
  <Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <!-- Title bar -->
    <Grid HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch">
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
      </Grid.ColumnDefinitions>
      <Grid.Background>
        <LinearGradientBrush EndPoint="0.5,1"
                             StartPoint="0.5,0">
          <GradientStop Color="#FFE3EFF7"
                        Offset="0" />
          <GradientStop Color="#FFD6E7F3"
                        Offset="1" />
        </LinearGradientBrush>
      </Grid.Background>
      <TextBlock Name="TitleTb"
                 HorizontalAlignment="Center"
                 Text="Title"
                 FontWeight="Bold" />
      <Button VerticalAlignment="Center"
              HorizontalAlignment="Right"
              Grid.Column="1"
              Margin="5,3"
              Width="14"
              Height="14"
              Padding="0"
              Click="Button_Click">
        <Button.Content>
          <Image Source="/TestingPixataWithFerrets.Client;component/Images/closebutton.png"
                 Width="14"
                 Height="14"
                 HorizontalAlignment="Center"
                 VerticalAlignment="Center" />
        </Button.Content>
      </Button>
    </Grid>
    <!-- Main content area -->
    <Grid Grid.Row="1">
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
      </Grid.ColumnDefinitions>
      <!-- tea cup RSS icon -->
      <Image Width="64"
             Height="64"
             Margin="8"
             VerticalAlignment="Center"
             HorizontalAlignment="Center"
             Source="/TestingPixataWithFerrets.Client;component/Images/rss.png" />
      <TextBlock Name="MainContentTb"
                 Grid.Column="1"
                 Margin="3"
                 Text="Main content" />
    </Grid>
    <Grid.Background>
      <LinearGradientBrush EndPoint="0.5,1"
                           StartPoint="0.5,0">
        <GradientStop Color="#FFFF9B00"
                      Offset="0" />
        <GradientStop Color="#FFF8D183"
                      Offset="1" />
      </LinearGradientBrush>
    </Grid.Background>
  </Grid>
</uc:PixataToastControlBase>

If you look at this in the Visual Studio designer, it will look like this...

The new toast in the VS designer

Looks pretty much like the previous ones eh? It is, but we are going to do one thing differently, and that will make a lot of difference.

Switch to the code behind, and override the TitleText property as before, as we are using a plain string for the title. However, instead of overriding the MessageText property, we are going to expose the MainContent TextBlock control, so that the calling code can manipulate it. Change the code to look like this...

using System.Windows;
using System.Windows.Controls;
using PixataCustomControls.Presentation.Controls;
 
namespace LightSwitchApplication {
  public partial class ToastWithPeanutButter : PixataToastControlBase {
    public ToastWithPeanutButter() {
      InitializeComponent();
    }
 
    public override string TitleText {
      set {
        TitleTb.Text = value;
      }
    }
 
    public TextBlock MainContent {
      get {
        return MainContentTb;
      }
    }
 
    private void Button_Click(object sender, RoutedEventArgs e) {
      CloseMe();
    }
  }
}

Notice that we don’t override the MessageText property, so anything we pass in for that parameter will not be used.

Our new toast is complete, let’s see how we can use it. In a Lightswitch screen code-behind, add the following...

Dispatchers.Main.BeginInvoke(() => {
  ToastWithPeanutButter toast = new ToastWithPeanutButter();
  TextBlock tb = toast.MainContent;
  tb.Text = "";
  tb.Inlines.Add(CreateRun("DotNetWhatNot - ", Bold: true));
  tb.Inlines.Add(CreateRun("7th Mar '12 16:42"));
  tb.Inlines.Add(new LineBreak());
  tb.Inlines.Add(CreateRun("Toast control added to Pixata Custom Controls for Lightswitch", ForeGround: Colors.Brown));
  tb.Inlines.Add(new LineBreak());
  tb.Inlines.Add(CreateRun("Some MSDN Blog - ", Bold: true));
  tb.Inlines.Add(CreateRun("7th Mar '12 17:31"));
  tb.Inlines.Add(new LineBreak());
  tb.Inlines.Add(CreateRun("Microsoft announce new version of VS - no Lightswitch!!", ForeGround: Colors.Brown));
  PixataToastHelper.ShowToast("Latest RSS feeds", "", toast, Width: 400, Height: 100);
});

For convenience, this uses the following utility method...

private Run CreateRun(string Text, int FontSize = 11, Color? ForeGround = null, bool Bold = false) {
  Run r = new Run {
    Text = Text,
    FontSize = FontSize,
    Foreground = (ForeGround == null ? new SolidColorBrush(Colors.Black) : new SolidColorBrush((Color)ForeGround)),
    FontWeight = (Bold ? FontWeights.Bold : FontWeights.Normal)
  };
  return r;
}

This utilises a little-known feature of the TextBlock control, that you can add formatted multiline text to it by manipulating the Inlines collection, which can take Run and LineBreak objects. Using this utility method, we build up a list of two RSS items, which in reality would be pulled from your data source. I hard-coded the information to keep the example simple.

The result of this is the following toast..

The new toast

That’s a definite improvement over yesterday’s toast!

Obviously, you don’t need to do all that work creating Run and LineBreak objects if you don’t want, you can just add more controls to the toast’s XAML, and expose their Text (or other) properties from the toast control. That way, the code you write in Lightswitch can set up the toast as you want before passing it to the ShowToast method.

I hope this post has whetted your appetite for creating more interesting toasts. If you have a toast that you feel would be useful to others, or just want to share an interesting creation, please let me know.

Wednesday, 07 March 2012 17:54:00 (GMT Standard Time, UTC+00:00)