views:

1740

answers:

18

I've been working in Silverlight recently and I've slowly been discovering that as simple as it can be to develop, there are one or two annoying gotchas that lurk in the shadows.

Considering how difficult some of these have been to track down for me, I thought it might be useful to list them here on SO for others to benefit from. I'm sure the ones I have encountered are nothing compared to the experience of others and I'd like to try and avoid any other nasty or time consuming surprises.

So, what have you got?

Update
I've updated this to cover Silverlight in general. Therefore, please provide a version or list versions to which the gotcha relates when responding. For all those without a version, please assume Silverlight 2.0 as this was the case in the original question.

+10  A: 

The two that I've experienced are:

Cross Domain Policy Files

For Silverlight to work with Web Services that are hosted on a different domain, the server needs a cross domain policy file. This can take two formats:

  • clientaccesspolicy.xml
  • crossdomain.xml

I couldn't get the former to work properly but the latter worked (Flash uses the second one whereas I believe the first is specific to ASP though I couldn't get it working under an ASP.NET 2.0 server, so it may be 3.5-specific).

ComboBox dropdown resizing

The Silverlight 2.0 combobox control only sizes its dropdown area once, when it is first shown. It therefore bases it's size on the initial items in its list. That means 2 items will give you a 2 item high dropdown, even when the list increases to 200. The only way around this appears to be to replace the combo with a whole new control each time the items change.

Note that setting the Height property or the MaxHeight property to a value that leads to items appearing off the list in the initial display of the dropdown will lead to an absence of a vertical scrollbar and therefore, an absence of access to items in your list. The only solution I found to that was to use the MinHeight property to at least have a decent height for all uses and just let it be bigger if the items exceed that minimum height.

Also, when you resize the browser window, regardless of whether you use MinHeight or not, and then either dropdown the combo list or you resize while it is visible, this can irreversably decrease the size of the dropdown.

Update

Here is a really nice solution to the combo problem, thanks to markti.

Jeff Yates
clientaccesspolicy.xml has nothing to do with .NET 3.5 or ASP or ASP.NET. Silverlight will try request the clientaccesspolicy.xml file first and then the crossdomain.xml file to maintain compatability with Flash.
Ray Booysen
@Ray: Then I have no idea why it doesn't work for me. :)
Jeff Yates
+6  A: 

Missing a double click event was one for me. I was amazed that is isn't in there and kept looking in the intellisence list :-) Solved it by creating a hack on it, but that's not a solution.

erik
I was not aware of that.
Jeff Yates
Yeah, it is quite irritating.
unforgiven3
A hack? Or a properly designed double-click implementation that takes 10 minutes to write?
Ray Booysen
+7  A: 

ComboBox weirdness

One thing that Jeff Yates mentioned in his reply was weirdness with ComboBoxes - I've seen that one personally, and I've also seen another very, very irritating issue with them. If you try to change the items in a ComboBox from the event handler for a button's Click event, you will get a cryptic error message which I can't think of at the moment. My solution to it was to do the same thing as in Jeff's solution - remove the combo box, construct a new one, fill that one with the changed item set, and add that back to the containing panel.

No ElementName binding

Silverlight has nothing analagous to WPF's ElementName binding ability. This post has a good workaround that has worked pretty well for me.

No support for mouse scroll wheel events

There is no native support for capturing mouse scroll wheel events. This post provides a solution that uses browser events for it.

No Unloaded event on UserControls

There is a Loaded event, but no Unloaded - if you want to remove a control from the screen and run some unloading logic, you need to roll your own way to do so. I have an IUnloadable interface that I derive my controls from that need to run unloading logic and invoke a method on it manually when the time is right.


And finally, this post has some good info about what Silverlight is missing as compared to what WPF has.

unforgiven3
I was only aware of the last one and didn't know about the workaround. Thanks for these. :)
Jeff Yates
A: 

You probably mean beside that it's just ActiveX2.0 and that we've been there and done that and that it didn't work the first time...?

Thomas Hansen
XYZ... your ignorance is showing...
jcollum
+3  A: 

A while back I did a project in Silverlight 2.0 and the project was driven using TDD and MVP. My service references were located in a seperate assembly so the view need not know of the model. I had a gotcha with the location of the ServiceReferences.ClientConfig file which needs to be in the view's assembly!

This file is generated if you add a service reference. We were added a WCF Web Service, but I was new to Silverlight and so didn't know that the Silverlight applications are compiled and packaged as a XAP.

If your ServiceReferences.ClientConfig file isn't located inside this XAP you have problems.

So there's my two cents worth. I posted this a while back on the Silverlight forums and it seems I'm not the only one this gotcha applied to.

My Original Post

vanslly
Good one, I ran into this too a while back.
unforgiven3
+4  A: 

One that got me recently was that there is no LayoutTransform property (although there is a RenderTransform property). Therefore, you cannot apply a transform and have the adjacent elements respect the 'new space requirements' of the control, which will then cause it to overlap with other elements or have blank space.

This was a problem for me because I wanted the scrollable area inside of a scroll viewer to change with the transforms. I was able to get around it, but the process would be much more difficult if you were trying to rotate or do another transform.

Travis
+3  A: 

Using IE6 and the website hosting the Silverlight App has compression enabled (HTTP 1.1 Headers)

Whenever you make a web service call it just fails even though Fiddler shows the request being sent and the response arriving successfully.

Graeme Bradbury
This is useful to know. Thanks.
Jeff Yates
+3  A: 

I have found that debugging support is incredibly flaky. It worked for me once but never since, no matter what I try. I think that it may only properly work when debugged via an ASP.NET 3.5 site using the Silverlight ASP support.

Solved

The issue was with using Google Chrome. Because Google Chrome hosts Silverlight in its own process, the debugger couldn't find it. If you debug using IE7, it attaches fine, but if you debug using Chrome, you have to manually attach to the appropriate Silverlight task under Chrome before it will work.

Thanks to mattmanser for the clue as to what the problem might be.

Jeff Yates
+2  A: 

Debugging can be tricky, if it's not working it might be because you're attaching to the wrong code type on the process. Try manually attaching to the process and make sure you've got 'silverlight code' selected instead of 'managed code'. From then on it will probably work all the time again.

mattmanser
+2  A: 

Oh there are loads. Lets start with 3 Browser gotchas:

Anything but IE: The Silverlight object won't scale to fit the browser window. Workaround: Put this between the tags:

<style type="text/css">
  html, body, form { height: 100% }
</style>

Also be aware that IE will let you have your dev website in localhost and your app access other domains, whereas other browsers won't.

Safari: If you use custom response headers (which are useful for doing efficient paging in Data Services) Safari may change the case of the header names breaking your app.

Visibility issues

There are various issues with changing properties of collapsed visibility components, generally what happens is they don't register the change while they're not visible and you have to do them again when you make them visible. The SL team seems not to have tested very thoroughly what happens when you make components invisible and visible.

If you are getting an unexpected intermittent ArgumentException, this may well be because you have code in a button's click event which makes the button itself (or a parent of it) invisible. Apparently some internal code runs after the click event which is expecting the button to be visible. Get around this by creating a short (100ms for instance) DespatcherTimer in the click event, and setting the button invisible in the Tick event.

DependencyObject / DependencyProperty issues

If you're used to the way these work in WPF they are thoroughly broken in Silverlight. If your data objects are DependencyObjects you will have 2 problems. One is that in SL DependencyProperties don't have change notification built in - if you want them to update bindings you'll need to make your object implement INotifyPropertyChanged. Another is if you bind to a collection of DependencyObjects you will get very wierd effects. You need to use a class a little further down the control hierarchy - I've inherited from FrameworkTemplate instead. So I'd recommend your data objects look like this:

public class CustomDataObject : FrameworkTemplate, INotifyPropertyChanged
{ ... }

Converters

There's no multivalue converter and no Binding.DoNothing. No workarounds for these I know of.

James Ellis-Jones
A: 

It is frustrating that Silverlight swallows so many exceptions when debugging.

A: 

Message Box

I was working with the System.Windows.MessageBox static class recently (currently, the only way to get something close to application modal - rather than just UI modal - user feedback) and I discovered the irritating focus handling whereby the message box returns focus to the browser rather than the Silverlight control that had focus before the message box was displayed. This is no doubt due to the Silverlight plug-in using the browser to show the message box, but it is irritating none-the-less, and combined with the limited options available for customizing the message box, it was soon apparent that I needed something else to provide my user feedback.

Blocking user interface access when showing a popup...

After searching the Internet, it was clear that I would need to use some kind of user interface modal display based on the Popup primitive. So, I rolled my own modal dialog box class and I discovered another issue in the process.

The user interface beneath the popup remains active which means tabbing around will give you access to the controls you're trying to hide. To mitigate this, I first tried disabling the page by getting the RootVisual (i.e. the page) and setting IsEnabled to false. This worked great, until I used my dialog box during a DataGrid edit operation. The dialog code worked twice and never again. It seemed that disabling and enabling the grid during an edit caused some kind of unrecoverable issue in Silverlight (possibly a memory leak as it eventually crashed).

It turns out that to achieve what I wanted, the easiest way is to set focus to something in my popup dialog and to set the TabNavigation property to KeyboardNavigationMode.Cycle. That way, focus never leaves the dialog and so the underlying UI remains out-of-bounds, but without creating the aforementioned issue.

Jeff Yates
A: 

Control's parented by resources...

Declaring a control in resources and then trying to parent it to a Popup later will result in an exception stating that the control already has a parent. In this scenario, there is no way to detect what the parent is and to remove it (I tried many different ways). The workaround was to wrap my control in a popup in the resources and then make my code either re-use that popup or just discard it in favour of my own by reparenting the control. As the control can identify the popup as its parent, this is easy to do.

Jeff Yates
you can get around things like that by putting styles in the resource and applying them to instances of your control in the popup or whatever (most of the time)
Ciemnl
A: 

Modal Pop-Ups Not Supported Solution -Create a User Control that expands the entire canvas and set the opacity to .05 as seen on ScottGu's sample Silverlight application http://weblogs.asp.net/scottgu/pages/silverlight-2-end-to-end-tutorial-building-a-digg-search-client.aspx

Datasets not supported Solution - Use LINQ to XML that can read XML into a generic list for databinding purposes

Master Pages not supported Solution - Create a parent XAML page, and have the rest of the application created using User Controls so you can switch between them

Namespace problems occur when using the AJAX toolkit together with the ASP.NET Silverlight tag.
Solution - Use the OBJECT tag instead of the ASP.NET Silverlight Tag.

I find using the Popup primitive to be a better solution as it doesn't dictate the layout of the underlying application. This solution dictates that your Page must use a Canvas as its root element whereas the Popup solution allows for a solution that can be used regardless of the root element.
Jeff Yates
+2  A: 

No Credentials available on web requests

The Credentials property is not available on the WebClient or HttpWebRequest. You need to run the request through a proxy service that will do the credentials.

Glenn Slaven
+3  A: 

The HttpWebRespone can only have one of two status codes

  • 200 OK
  • 404 Not Found

That means all other errors are mapped to 404, which is quite annoying. I don't know how redirects work (I hope they are being followed automatically...)

http://msdn.microsoft.com/en-us/library/system.net.httpstatuscode(VS.95).aspx

chris166
+1  A: 

OpenFileDialog/Isolated Storage

In order for your app to initially use or increase local storage, you have to specify how much space you need, and then Silverlight prompts the user if he/she wants to allow the change. That's all good. But there's a catch: If you open a file dialog, there is no way to obtain more storage after that point. In my scenario, the user selected file(s), I processed them, and then calculated how much space I would need to save the processed file. But because of this issue, I had to guess what the maximum size of that file would be, and ask for storage based on that. If the file was larger, the user would have to do the whole process over again.

Layout system

This really sucked. Until you explicitly set an element's size, you get NaN for all size properties. You can hook into every resize event and get the values there, but in most case you can't just ask for a height or width and get what you want.

No LayoutTransform

Mentioned above by Travis

Chris
+1  A: 

The fact that there are so many different releases in a short period of time.

Good - things that are frustrating get fixed quickly. for instance mouse scroll wheel, right click - fixed in Silverlight 4.

Bad - if you're new you have no clue if a documented 'hack' is still necessary or not. I'm starting fresh with Silverlight 4 and finding a tonne of tutorials and help - but never quite knowing if they're up to date or still the best way to do it.

Simon_Weaver
just realized the title of this post is 'biggest gotchas in silverlight 2'. hope its ok to mention 4 !
Simon_Weaver
@Simon: Yes, that's fine. I think the question has to keep up with the times. :)
Jeff Yates