Mike Kenyon

Hoarked
posts - 10, comments - 4, trackbacks - 0

My Links

News

Archives

Saturday, February 14, 2009

The Oscars with Style – Part 1

The raw, basic functionality of my Oscars application is now up and running.  Next job is to get the application up and looking pretty.  This is without a doubt, at the moment, the ugliest application I’ve ever built and was intentionally.  The goal was to do all the functional work first, and then tackle the “look pretty” work.  Well, that time has come. 

Defining the “Look”

So I’ve got to decide on a look to go with for the application.  I want everything to feel like it should fit together, so I spent a little while thinking through what I want it to look like.  When I think of the Oscar’s, I think of the Mann Chinese Theater, the red carpet and things in Black & Gold. So I think that’ll be my theme.  What I’d REALLY like is to have a 3D scene in the background but I’m just not that good with 3D.  I can do some nice shading with black and gold and get a fairly attractive app.  Here’s the main screen before styling.

Before Styling - Main Page

Here’s the same screen with a little styling applied …

1a

MUCH better…. still some issues.  I’m being lazy at the moment with icons for the top-right and since I had to, I figured out the resource loading issue, so I should go back and remove them as actual buttons and use the ModeSelector type I made back at the start.  Right now, I’m excited to make progress aesthetically, so I’ll save it for cleanup before I get to to adding features.

Browse Pages

The browse pages were fairly easy to style as well.  The main categories page was just four buttons.  We needed to come up with something a little flashier.

2b 2a

When I got to the This required that I start tracking an image on the category, which is fine, because I started thinking about it and it should probably show the winner’s picture after they win.

For the type listing page (listing all categories, movies, what-have-you, I wanted VERY much to get a nice grid-array.  This tripped me into two major problems.

First, it was slow, butt slow.  At least, it was slow when I was showing People.  If I showed Songs it was great, of course, there are only three songs and pushing 600 people.  I was forcing a new image source for each image,which was costly.  So, I gave up a little abstraction and converted the business types to return image sources.  I thought about coding VIewModel wrappers for them all to do just that, but it seemed excessive for the degree of violation of abstraction that it was.  Pragmatism sometimes needs to rule. 

Second, I was using a wrap-panel to represent things (like I did on the main categories page and that wasn’t great.  I decided I needed to virtualize.  There’s great though about making a VirtualWrapPanel on the Internet, but the only guy I can find to do isn’t giving up the source.  I didn’t have time to get the panel and scrolling issues taken care of.  I really just wanted to steal something, so with a little creative Google-foo, I found the VirtualizingTilePanel, which is close enough for government work.  The hardest part was getting the scroll-bar styled nicely.  There’s just a lot of moving parts there.  None of them are hard, you just to put some thought to what you’re looking for.

Content Pages

For the content pages themselves, all I needed to do was to add a DataTemplate for each of the 4 stylized approaches.  This works out great.  Check out the different stylings just by setting the default style for the data template for the module.  The “before” pictures were just the name of whatever it was twice, so I’m going to skip over that if no one minds …

4p-a 4m-a

4s-a 4c-a

 

Making a Splash

So, somewhere in this whole deal, I downloaded the WPF Futures Splash Screen add-on and turned it on.  In about 0.222 seconds I had a VERY nice splash screen for application startup.  I was impressed.  It’d be nice if Prism integrated a little better here.  The splash screen comes down when the main window comes up, which is well before module loading has completed, so there’s a couple of minutes of dead-time before the modules kick in and the app is actually usable.  All you need to do is add an image and then set it’s BuildAction to SplashScreen.  It couldn’t be any easier.

Backing Up

I found it really necessary to add a back button, which gets us back to our whole issue of the navigation.  My first cut at this was to just add a button that knew what the previous page would have been and re-activate that.  The downside was that that’s REALLY taxing to do, breaks a lot of encapsulation and the whole idea goes out the window when I start having the browse pages link to one another.  So, I needed to create a navigation service.  Once that was in place, I just made everything a button or hyperlink bouncing it to the appropriate navigation service.

I did this in two parts.  First, I wanted an easy way for the different pages to link to a spot, so I created an IOscarsNavigationService that provided methods to allow you to link to interesting areas without having to know anything about them.  I put the definition in the foundational module OscarsNight, but the implementation I put in the Browse module as this is logically where the smarts to the do the work are located.   Once I had the service in place, I followed the How to: Create Globally Available Commands guidance from the Prism docs to create a global ItemNavigate command, which the Browse module intercepts to navigate any INamedEntity that might happen to be navigated to.  I had already created a single, named DataTemplate that I used to describe the little icons I was dropping all over the place with cross references in them.  By associating the command with the template everything suddenly became navigatable!  I then dropped like 40 lines of code (mixed XAML and C# code) that had been doing navigation and I got a clean implementation back that gets rid of list boxes, and just shows everything as being a link.

The second part was trying to clean-up the Back button that was now everywhere.  I actually wanted it to go back, but that requires understanding what “back” means.  I needed a stack.  I needed to track what the active view was at any given time.  I thought about doing it with a behavior, but I don’t need to and behaviors really are great when you want the behavior to apply to all regions of a specific type.  In this case, we want to handle exactly one region as the navigation locale, so I think we’ll pass on it.  A little playing around got it working pretty quick, which allowed me to clean out a bunch of code dedicated to supporting the hack I had had in place.  The code is now starting to look clean. 

Future Proofing

I’m a big fan of planning for the future … if it’s easy enough and in this case it is.  I know that I’m going to want to add more information to what I have stored on the different objects in Browse, but I don’t know what and as they’re going to be later add-ons, I don’t want to have to know.  So what I did was I added an ItemsControl to each of the data templates that style the navigatable types and marked that items control as being a region.  This enables me to register views with the region and through view discovery, they’ll auto populate whenever the page pops up.  As the types will invariably need to see the thing being presented, I made that the RegionContext of that region.

 

Next up the voting module …

Here is the code.

Posted On Saturday, February 14, 2009 4:28 PM | Feedback (1) |

Creating a WPF Application With Prism v2 – The Final Frontier

Okay, recap.  We got the shell of the application up and running.  We’ve made two foundational modules to provide functionality to the business modules.  We’ve created a couple of business modules to allow people to browse the nominees and to allow them to vote.  We’ve refactored more times than I care to count.  We have also created possibly the ugliest application I’ve ever been associated with.

Left on the plate?  We’ve got the last major business module to write (that being the module that scores the Oscars when they’re on).   Next we’ve got a lot of styling to do.  Let me repeat that.  We’ve got a lot of styling to do.  Following that, we’re on to bells and whistles (like song clips, player photos and critical reviews).

Score Module Design

So, I’m down to the last module to create.  In some ways, it’s the most complex, in others, its the easiest.  I’m thinking in my mind that there are three major capabilities.  First, they’ve got to be able to pick a category.  God only knows what order they’re going to do the categories in, so I need to be able to pick in a random access fashion.  There are some general rules (best supporting actor tends to come first, best picture is always last, etc.).  Second, they need to be able to pick a winner.  The designer mind clicks in here and I’ve got a mental image of it being the 4 or 5 part split, but no matter how you cut it, at the moment its a list box.  Third, we want a leader-board, so that people can brag amid-game. 

Part of me says to keep things simple and make it as three separate views, part of me says life will be easier with one.  I’m going to take the latter approach till I find a reason to split it out.  Refactoring is life after all.

I don’t want the category selector to take up that much room, so I think I’ll plan initially on it being something like the selector control out of Kevin’s Bag of Tricks (which you should look up if you’re not familiar, a great tool to understand and learn WPF).  Barring that, I may decide that the carousel on a path is a better option, we’ll just have to see what the designer wants.  Either way, a ListBox is the correct choice for the actual control to use, everything else can be taken with styling.

For the leader-board, I don’t want a section model, the data should auto sort with the leaders on top.  I’m going to put it as an ItemsControl (it has multiple values and no selection model).

WPF Philosophy Aside

One of the things that I love best about WPF is the philosophy of developers designing by function and designers designing by appearance.  I’ve been an advocate of <strong/> and <em /> over <bold /> and <italic /> since the early, early days of the web.  I’ll admit my limitations and while I can make just about anything look the way the designer intended, coming up with that intent often alludes me.  As a developer, how it functions is more important to me than how it looks and WPF supports, embraces, nay insists on this separation.  If you don’t take it, it takes it for you through the use of styling.  The fact that I’m (as a developer) responsible for how something logicallly is laid out frees me from bit-twiddling to figure out why I’m 1-pixel off somewhere and let’s me concentrate on the important things.  It also means that I (as a designer) am responsible for the aesthetics and experiential behavior of the application and don’t have to worry about what and who gets called for what. 

I find myself using precious-few actual controls in actual user controls.   Typically, it’s ContentControl, HeaderedContentControl, ItemsControl, ListBox, Button, CheckBox and layout panels.  Just about everything else I can do styling.  Theoretically, I don’t even need panels, because I can use an ItemsControl and set the ItemsPanel for the control in the style … actually, that’s a pretty good idea.  I may refactor to do just that.

Flipping State

One of the things that I’ve noticed is that I tend to end up recreating views over and over.  This generally isn’t horrid.  There’s some gap in my activate vs. create logic that I’ve got to take care of.  In most cases, I’m displaying data out of a service and therefore don’t care, because the service itself is a singleton.  In this case, I don’t have a service (as a moral thing, I don’t create a service if one view is the only possible consumer) so I need to store some state that will will live between creations of the control (just in case).  I could store it in the database, but it’d be a couple fields and persisting the winners doesn’t really interest me.  It means I have to clean things out when I’m testing and I hate that.  So, I’ve got two real pieces of state.  First, who won each category.  Second, the leader-board.  The winner seems a perfect case for an attached property again.  This way, I can store data on someone else’s type without having it be (necessarily) readily apparent, public knowledge. For the leader-board, I’m going to store it in the Application object which has a hashtable for exactly this sort of situation.

For the leader board itself, I’m going to just make a derived ObservableCollection<Player>.  This gets me everything but sorting and I can throw an event handler to sort the list every time the player’s score changes.  So, how do I represent the scores?  I think that’s another great case for an attached property on the Player itself.

Without much problem at all, I got the system up.   Now onto styling.

See it here.

Posted On Saturday, February 14, 2009 9:56 AM | Feedback (0) |

Powered by: