Wednesday, July 20, 2011

Creating a custom SharePoint navigation menu

While working on a public facing SharePoint website I was asked to build layout that worked well with mobile devices.  For the most part I achieved this by editing the master page and then choosing which CSS file to link to based on whether or not it was the mobile page was being requested.  This approach worked well for most of my content, but the standard SharePoint navigation menu was somewhat problematic in that it lays itself using tables and is rather complicated.  I wanted it to be much simpler and just use a simple unordered list.

I ended up writing a custom ASP.NET control to do just that.  Of course I want the new menu to respect the same visibility settings for the different links and to stay in sync with changes to the sub site names.  The best way to achieve this is to use SharePoint’s built in site map.  My code ended up looking like this:

And the markup:

Sunday, July 3, 2011

What is wrong with WPF?

When WPF was first announced, I got me extremely excited.  I watched a number of the early demos and saw what was possible in terms of styling and animation and it just seemed amazing.  One demo showed how simply a ListBox’s template could be changed to display as a map of the world and each item was a country. Combine that with the promise of rich media support and hardware acceleration and I was convinced WPF was going to be the best thing ever.

Such was my excitement that I started working with WPF as soon as I could get my hands on it.  I have been working with it professionally since 2006 and over that time I have found a number of problems that routinely rear their ugly heads. I find it hard to stop thinking about a problem until I have a solution, but the nature of the problems combined with the fact WPF closes up so many possible extension points means I haven’t been able to come up with a solution using WPF as we know it today.

This combined with my OCD desire to solve problems has caused me to spend a lot of the time I should be sleeping thinking about how I could design a successor to WPF that was free of these problems.  Unfortunately I don’t have enough spare time to actually build the thing so I asked the tweeps to convince me I shouldn’t waste my time by starting to write a replacement. @jtango18 asked me why I would want to in the first place and this post will attempt to answer that question.

Poor design experience

One of the much touted features of WPF was supposed to be how it enabled designers and developers to focus on what they were good at.  Blend being the tool for designers and Visual Studio being the tool for developers.  The problem is that Blend is only any good for doing a design when you have some data to display and tends to fall down quite badly if you have certain constructs in your XAML or code behind.  Everything will work when you run the application but the designer just blows up.

Blend does have tools for generating some design time data, but this is limiting because of the time it takes to set it up and it also won’t work if you have different data templates which are selected based on the type of the object you are displaying.  There are many other small annoyances with using the designers, but the thing that frustrates me the most is that I often have to run my app, navigate to the part I am working on look at it, then go back and tweak the design and repeat infinitum.  When you are trying to decide on the best margin or colour for something in a data template I find my self wasting enormous amounts of time repeating that cycle.

My UI framework would be built with this in mind and would allow the designer to attach straight to the running process and edit the view live.  You could make use of the real data and get instant feedback as you made changes even when you are 3 or 4 templates deep.  I think this might actually be achievable with WPF as some of this can be done using tools like Snoop, but it would take a lot of work to get it to the same level of functionality that Blend supports.

Poor Animation Performance

I simply cannot understand this one, but I suspect it boils down to rendering performance.  I have often found animations involving a few objects, especially objects that have a few effects applied (eg drop shadow) do not animate smoothly into position.  I refuse to believe that my laptop is incapable of rending a few UI vector shapes moving around with a couple of simple effects applied smoothly.  For crying out loud it can render this @ 60 frames per second at 1920 x 1200 and it has to do extra work like updating physics for 100s of objects:

982059671

Animations Fail To Play

Quite often when you have a UI component that has different states you would like it to look different in each state.  In .NET 4.0 the VisualStateManager was added to help with this sort of thing.  However I sometimes find animations between states, or animations that should loop while in a given state simply fail to play some of the time.  I have never been able to get it to work 100% of the time, it will work most of the time and then just fail for no apparent reason.

I encountered similar issues before the VisaulStateManager was added to the framework and in those situations it boiled down to not being able to apply the animation, because another animation was already applied to the object.  Given that animation was one of the key things WPF was supposed to make easier it is more than a little silly how many workarounds I have to use to get it to work properly.

Drag and drop

There is no inbuilt support for doing drag and drop with nice Windows shell effects, such as drag descriptions and thumbnails.  WPF is supposed to be about creating rich user experiences, but it doesn’t even let you easily do shell style drag and drop.  I have implemented a bunch of Blend behaviours which make this possible, but you wouldn’t believe how much trouble and how many hacks I had to use to get them to work properly without flickering.  Not to mention how MS decided to make the methods for accessing the mouse’s screen coordinates internal, you need the screen coordinates to prevent accidental drag and drop operation when the view is scrolling.

Missing effects

When you are trying to design a nice looking UI, gradients and drop shadows can go a long way.  Inevitably though you wind up wishing you could use a bevel, inner shadow, inner glow and maybe an outer glow.  If you have worked with Photoshop you will know how these effects can be used to create some quite striking visuals, but alas WPF doesn’t have support for them.

You can off course get some of these by using the old bitmap effects, which works fine as long as the object you are applying it too is tiny, but as soon as you add it to a big object things start to chug very very badly.  No worries I hear you say, you can just write your own graphics shader to do it for you.  Unfortunately WPF doesn’t support multi-pass shaders which are required for these effects.  Well actually it sort of does, the built in shadow effect does use multiple passes, but they don’t expose that functionality to you so you’re stuck with a single pass.  The end result is that you end up using lots of PNG images made by Photoshop and you can kiss your resolution independence goodbye.

Video and other media support is poor

I have worked on a couple of projects where the level of support for video playback in WPF has been very disappointing.  In both cases I ended up having to ditch WPF and go back to WinForms in conjunction with DirectShow.  WPF is fine if all you want to do is play a video here and there, but as soon as you want to do more than that you run into problems.

For example say you have multiple videos all playing at once and it is imperative that they stay perfectly in sync with one another.  This is not possible in WPF because your access to the underlying resources is too limited.

Another example, you would like to have one video playing in a loop and then, when the user presses a button immediately start playing another video with no noticeable pause between the videos.  However there is no way to tell WPF to buffer a video other than to play it, you can play it and pause it, but you still don’t know when the buffering is complete so it is hard to transition between the two.

Triggers are messed up

When I was first learning about triggers I thought they were awesome, but after you learn the limitations it starts to disappoint you.  For example you can’t use data triggers outside of a data template, why is that?  Then there is how you can’t say you want the trigger to fire when the value is not equal to the one you provide.  I actually spent quite a bit of time digging about in Reflector for a way around that one and eventually discovered that underneath it all triggers actually do support the idea of not equal, but it is never exposed anywhere.  I couldn’t make a nice fix for it though, because the trigger collections test to make sure they only receive specific implementations.  That just plain sucks, why can’t I write my own triggers? 

Some would say so I can’t so that I don’t write triggers that perform badly and then blame MS for poor performance, but I think that is the stupidest reason ever.  By giving me more power, sure it does increase the ways I can blow my head off, but it also lets me do amazing things that no one has thought of before.  Given that I’m a responsible adult let me decide if I want to play with fire or not, I won’t blame you if I burn my self.

Implementing Virtualizing Panels is Hard

So you have a list that has hundreds or thousands of items and you want to scroll smoothly.  You can sort of get away with the built in virtualizing stack panel, but it isn’t smooth and if you have your own layout you can forget about it all together.  We need a way to solve this problem that doesn’t take many, many hours to get something that is passable.

Binding Memory Leaks

By default if you bind to a POCO object that doesn’t implement INotifyPropertyChanged you get a memory leak, where the object you are binding too will never ever be garbage collected.  This is crap and should not happen.

Lack of composition and extension points

WPF was supposed to be all about composition over inheritance.  Control and Data templates do to some degree achieve this goal, but I just wish they had applied the same thinking to the rest of the framework.  For example the Button control’s inheritance hierarchy has eight classes before you get back to object. There is a school of thought that suggests that if the team had realised the power of attached properties earlier a lot of the functionality would be implemented as something like Blend behaviours instead of separate classes.

This inheritance tree can makes things rather difficult, because quite often you end up having to have a case in your code for both FrameworkElement and FrameworkContentElement, why the hell they don’t implement a common interface I have no idea.

When you put this together with so many places where your ability to extend the framework has been deliberately limited (eg triggers, low level video access and multi-pass shaders to name a few) you end up with a sour taste in your mouth.  I have spent many hours over the last few years getting around these problems in software projects I have been working on, but if WPF was just built a little differently I wouldn’t have the problem or there would be an elegant solution rather than painful hacks.

In Conclusion

So am I crazy and these problems only exist for me or have you had these problems too?  Feel free to leave a comment or haggle me @calebvear on twitter, I would love to hear about your experiences.

PRIEMTIVE NOTE: I have heard some of the news about Windows 8 and the new DirectUI and Jupiter APIs. Of course at the moment most of what I have heard seems to be largely speculative. I do hope that it will solve many of the issues I have today, but I doubt it will solve all of them.