EasyPlayer shell outline
Looking back at the plan, I want a simple shell: across the top is space for an 'SuperBar'; down the left we have the widgets; the body has the selected widget's controls. As XAML isn't the most terse of formats, it's probably easier to see on GitHub, but I've used a simple Grid for the main layout. I'm not sure if this is equivalent to using a table for layout in HTML, but it's simple enough at this point.
I'm hoping there's an equivalent to CSS in Silverlight. I'm going to keep the initial layout pretty plain and then hope to come back to it later. For example, it'd be nice to add some fancy smooth transitions when widgets are swapped in and out, but that's a definite feature for later!
The main point of interest is the way Caliburn.Micro leads the structure of the application. I have to say I'm really liking it at the moment! The main screen, ShellView.xaml has no code-behind but has an associated ShellViewModel.cs. Databinding is then used to populate the widgets. So in the XAML, the list of widgets is currently an ItemsControl:
<ItemsControl x:Name="Widgets" Grid.Row="1" Grid.Column="0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Button Content="{Binding Name}" cal:Message.Attach="ActivateWidget($dataContext)"
Margin="2, 2, 2, 2" MinHeight="40"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Then to populate the ItemsControl with the available widgets, and to handle the click event of each widget, we have the ViewModel:
public class ShellViewModel : Conductor<IAppWidget>
{
public BindableCollection<IAppWidget> Widgets { get; private set; }
public IAppWidget ActiveWidget { get; set; }
public ShellViewModel()
{
// populate widgets - could probably be replaced by an IOC container auto-populating this collection
PopulateWidgets();
ActivateWidget(Widgets[0]);
}
public void ActivateWidget(IAppWidget widget)
{
ActivateItem(widget);
}
private void PopulateWidgets()
{
Widgets = new BindableCollection<IAppWidget> {
new LibraryWidgetViewModel(),
new Mp3WidgetViewModel()
};
}
}
I could have also eliminated my ActivateWidget method, and directly used ActivateItem from the XAML, but have decided to keep my method for the time being, just in case I need to do anything else when activating. Although I am treading the YAGNI line here.
That is the main part of the application at the moment. The library and mp3 widgets are very simple placeholders at the moment.
Why won't it work
I did have a really annoying problem. I'd written the code essentially as this version on GitHub, but when starting up the application, the widgets weren't populating. It was really frustrating: there's virtually no code so how could the sample application from Caliburn.Micro be working, and not my painfully simple application.
After about half an hour I found the problem. In the AppBootstrapper class I had the following definition:
public class AppBootstrapper : Bootstrapper<ShellView>
Which should have been:
public class AppBootstrapper : Bootstrapper<ShellViewModel>
And then it all suddenly came to life.
Next up, I'm going to take a look at using an IOC container and the continuous integration solution.
