A TimePiece of C# and JavaScript

I put together a little project on Github, partially because I’ve been making headway learning the intricacies of JavaScript, and partly because I wanted something that would parse a string that represents a time value. So here’s the TDD I went through. In the process I pulled in QUnit and used that as my testing framework for the JavaScript example. I’d love input on either of these, so feel free to gimme some heat, tell me what I’ve done wrong, and especially how I ought to be doing this.  🙂

The first thing I did was put together the C# Library. I started two projects, one for the tests and one for the actual library.  In the tests project I added a class file and removed the default using statements and replaced them with the following by way of Nuget:

[sourcecode language=”csharp”]
using NUnit.Framework;
using Shouldly;
[/sourcecode]

After adding these references I jumped right into setting up the test fixture. Since I know I want to have something to parse the hour for military time also I’ve setup two test variables.

[sourcecode language=”csharp”]
[TestFixture]
public class with_static_parsing_of_time
{
protected string sampleTimeOne = "10:12am";
protected string sampleTimeTwo = "2:30pm";
[/sourcecode]

The first test I then dived into was to test the hour.

[sourcecode language=”csharp”]
[Test]
public void should_return_a_time_piece_with_correct_hour()
{
var timePiece = TimePiece.Parse(sampleTimeOne);
timePiece.Hour.ShouldBe(10);
}
[/sourcecode]

I then fleshed out the object and implemented enough to get this test to pass.

[sourcecode language=”csharp”]
namespace TimeSlicer
{
public class TimePiece
{
public TimePiece(string time)
{
ParseTime(time);
}

private void ParseTime(string time)
{
SetHour(time);
}

private void SetHour(string time)
{
Hour = Convert.ToInt32(time.Split(Convert.ToChar(":"))[0]);
}

public int Hour { get; set; }
[/sourcecode]

I then continued back and forth writing tests and implemented each. For the complete code check out the Github Repository. This example is really simple. I’d love any thoughts on adding to it or what you might think is a better way to test the object.

For the JavaScript I downloaded QUnit. Again I stepped into the testing, which is a whole different ballgame than in C#.

[sourcecode language=”javascript”]
<link rel="stylesheet" href="qunit/qunit.css" type="text/css" media="screen"/>
<script type="text/javascript" src="jquery-1.6.2.js"></script>
<script type="text/javascript" src="qunit/qunit.js"></script>
<script type="text/javascript" src="TimeSlicer/TimePiece.js"></script>
<script type="text/javascript">

var timeValueOne = "1:30am";
var timeValueTwo = "8:15pm";

$(document).ready(function() {

module("Parse hour from value.");

test("Should parse hour from value.", function() {
TimePiece(timeValueOne);
equal(TimePiece.Hour(), 1, "The appropriate hour value is returned for AM meridian value.");
});
[/sourcecode]

For the full test file with other JavaScript libraries and CSS check out the code file on github.

…and directly into implementation. With the caveat that I’m extremely unfamiliar with actual psuedo/pretend/faux object creation in JavaScript. In this realm I’m still reading up on best ways to do this.

[sourcecode language=”javascript”]
TimePiece = function(time) {
TimePiece.Hour = function () {
return time.toString().split(":")[0];
}
return time;
};
[/sourcecode]

I went on from here writing tests and implementing as I did with the C#. The JavaScript was interesting. I’ve also noticed that I get a lot of strings back versus the number values that I’d actually want, thus the addition of the “parseInt” in the final version.

Check out the overall project on Github at: https://github.com/Adron/Time-Slice

A SQL Server .NET ASP.NET MVC RESTful Web Services Facade – Part I

Did I get enough of the acronyms and key words in the header?  It looks like soup!  :O

This is a somewhat messy project to build a prototype layer around SQL Server. The reason for this, shockingly, is to allow for a SQL Server to be used by frameworks and systems that normally don’t or can’t access the database directly. In my particular scenario we’re working on getting Ruby on Rails running with JRuby in a Windows Environment. Because we will need to utilize a lot of SQL Server Databases, it seemed like a great idea to build out a layer over the SQL Server (or Servers) so that a Ruby on Rails Web App, ASP.NET MVC, or even a PHP or pure Javascript Application could access the data in the database. What better way to do that then to create a RESTful Web Services Facade over the database.

Some of you might be thinking “Why not use RIA Services?!?!?! Are you mad!!” Well, there is a big problem, RIA Services doesn’t work against SQL 2000 or SQL 2005, which is the database technology that this particular requirement dictated. Well, now that you have context, I’ll dig straight in to what I did building this prototype out.

Kick Out a SQL Server Database Project

I need some data, and a database, with just some of the standard junk you’d expect in a production database. One of the best ways to throw together a database in a really short amount of time, with data, is to use a SQL Server Database Project.

New Database Project (Click for larger image)
New Database Project (Click for larger image)

You might see this and think, “But you said that the facade is against a SQL Server 2000 or 2005 database!” Well, it is, but to get a database running locally and have this project type work, I’m using my local SQL Server 2008 Express installation. However, I’m limiting myself to data types primarily available to SQL Server 2000 and 2005. So no worries, this works just fine against those archaic databases.  😛

First I ran the following script to create the database and some sample tables with various data types.

[sourcecode language=”sql”]
DROP DATABASE SomeExistingOrMigratedDatabase
GO
CREATE DATABASE SomeExistingOrMigratedDatabase
GO
USE SomeExistingOrMigratedDatabase
GO
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Person_Village]’) AND parent_object_id = OBJECT_ID(N'[dbo].[Person]’))
ALTER TABLE [dbo].[Person] DROP CONSTRAINT [FK_Person_Village]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Person]’) AND type in (N’U’))
DROP TABLE [dbo].[Person]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SomeFlatDenormalizedDataTable]’) AND type in (N’U’))
DROP TABLE [dbo].[SomeFlatDenormalizedDataTable]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Village]’) AND type in (N’U’))
DROP TABLE [dbo].[Village]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Village]’) AND type in (N’U’))
BEGIN
CREATE TABLE [dbo].[Village](
[Id] [uniqueidentifier] NOT NULL,
[Village] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT [PK_Village] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SomeFlatDenormalizedDataTable]’) AND type in (N’U’))
BEGIN
CREATE TABLE [dbo].[SomeFlatDenormalizedDataTable](
[Id] [uniqueidentifier] NOT NULL,
[StarzDate] [datetime] NOT NULL,
[Numerals] [int] NULL,
[Numberals] [int] NULL,
[Monies] [decimal](14, 4) NOT NULL,
[Day] [int] NOT NULL,
[Month] [int] NOT NULL,
[Year] [int] NOT NULL,
[BigNonsense] [ntext] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[Flotsam] [float] NULL,
[Jetsam] [float] NULL,
[SmallishText] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[BiggishText] [nvarchar](2999) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT [PK_SomeFlatDenormalizedDataTable] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Person]’) AND type in (N’U’))
BEGIN
CREATE TABLE [dbo].[Person](
[Id] [uniqueidentifier] NOT NULL,
[Name] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[DateOfBirth] [datetime] NOT NULL,
[VillageId] [uniqueidentifier] NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
END
GO
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Person_Village]’) AND parent_object_id = OBJECT_ID(N'[dbo].[Person]’))
ALTER TABLE [dbo].[Person] WITH CHECK ADD CONSTRAINT [FK_Person_Village] FOREIGN KEY([VillageId])
REFERENCES [dbo].[Village] ([Id])
GO
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_Person_Village]’) AND parent_object_id = OBJECT_ID(N'[dbo].[Person]’))
ALTER TABLE [dbo].[Person] CHECK CONSTRAINT [FK_Person_Village]
[/sourcecode]

Once the database and tables are created, import the database into the database project. To do this select the “Import Database Objects and Settings…” by right clicking the context menu on the Database Project.

Import Database Objects and Settings...
Import Database Objects and Settings...

Select the database just created and click on start. Once the script generation is done, navigate into the project directories and you will see the following scripts have been created.

Generated Scripts (click for larger image)
Generated Scripts (click for larger image)

Next create a new data generation plan in the Data Generation Plans folder (notice I already cheated and have one in the above image).

Creating a Data Generation Plan
Creating a Data Generation Plan

Open up the file this creates (I called mine BuildSomeData.dgen). In the file, note I selected the relationship between the Village and People Tables, and set the ratio to 60:1. When you change the data in the Village table it then automatically updates how much data will be generated for the People Table.

Data Generation Plan
Data Generation Plan

When all that is done, hit F5, select the database and the data will be generated. That gets us a database with data to use as an existing source. From here I’ll jump into creating the actual Facade Layer.

NOTES: Once you generate data, depending on how much you decided to generate, you may want to see how big your database is by using the sp_dbhelp stored procedure. I am however, unsure which versions of SQL Server this stored procedure is available in.

Code for this project is available here: https://github.com/Adron/ExistingSqlServerProject

HighBall Part Duex (#4) Patterns

Navigation of Highball Series Part #1 | Part #2 | Part #3 | Part #4

Here in part #4 I want to cover the final wire up I did to get the initial screens to show.  The other primary focus of this blog entry is to cover some of the architectural patterns behind what I have so far.  We haven’t touched upon testing this yet, primarily because I’m stepping through wiring both Silverlight & WPF with these libraries for the first time.  I’ve done the WPF before, but not both.  Soon enough, I’ll get back to good standard practice and get some tests done first.  But for now, here’s the low down on wiring up Silverlight and the architectural patterns so far.

Architectural Patterns & Ideas

Dependency Injection

This is one of interesting parts of the application, at least to me.  For many the dependency injection is endlessly confusing, but it comes in immensely helpful in getting things loosely coupled and all wired up.  Because even when you decouple things, they do have to get wired up again – it’s just the how that’s important.  Below is an example of a presenter in the schedule module that uses constructor based dependency injection.  Dig it?  I’ll have another follow up entry in the future about what and how Dependency Injection works, along with the respective Dependency Inversion, Inversion of Control, and all those other patterns.  For now, just now that this is how the view gets registered with the region that is responsible for displaying it when the application runs.

[sourcecode language=”csharp”]
public class ScheduleViewAllPresenter : IModule
{
private readonly IRegionViewRegistry regionViewRegistry;

public ScheduleViewAllPresenter(IRegionViewRegistry registry)
{
regionViewRegistry = registry;
}

public void Initialize()
{
regionViewRegistry.RegisterViewWithRegion("HighBallMainRegion", typeof(ScheduleViewAllView));
}
}
[/sourcecode]

In the code snippet above you’ll see in the initialize method that the view that is injected is registered to the particular region that it will be displayed in.  In the shell the view will be displayed in the region as shown below.

[sourcecode language=”xml”]

[/sourcecode]

Composite Modules

I’ve added a single module to the solution so far.  This module has two views & their respective presenters, which I’ll cover in the section below.  The module is simply a project, loosely coupled, that will provide a view and the presentation logic for that view to be injected into the shell upon some application logic.

The module itself isn’t so much a pattern but more an architectural piece of the application.  As I move forward on this project I’ll add more modules to the solution as functionality is needed.  Each module will have an isolated, or mostly isolated, business use.  The first example that I have is the HighBall.Interface.Modules.ScheduleModule.  I’ll be adding more, probably along these lines;  mileage tracking, vehicle inventory, driver check-in, driver route choice, etc.  Each having a particular part of functionality that will primarily be isolated to itself.

When the CAL is used within a development team the modules would most likely be split off to individual pairs in the case of Agile, or even entire teams.  In Agile parlance each module would be a number of user stories, or in the most simple form, a single user story.

View & Presenter, with no Model yet.

The view and presenter are where you get to see the Model View Presenter (MVP) first start to appear.  Eventually as I move forward there will be the model, and more elaboration on the view and presenter.  For now all we have is the view, which is just the xaml markup and the presenter which is responsible for registering the view in the registry, and initializing the view with a region that it would be displayed in.  As you can see above in the Dependency Injection example the presenter is very thin at this point.

So that summarizes the cut off point for my first basic release of HighBall.  Check out the code release, rant at me about deficiencies, and if you have any additional ideas or other elaborations you’d like to see please do comment.

Currently I’m researching how to put TDD into effect to build the presenters, views, and other composite pieces of this application.  My next entry will have several examples of unit tests that aren’t currently included in this release.  Until then, happy hacking (or coding).

HighBall Part Duex (#3) Wiring Up Silverlight

Navigation of Highball Series Part #1 | Part #2 | Part #3 | Part #4

In this part I’ll be covering wiring up Silverlight with an appropriate module similarly to what part #1 and part #2 covered for WPF.  What I want to show in this entry is basically the differences of each module and the difference in the startup shell.  The differences are however very minimal, which leaves me curious about abstracting some of this and removing the code duplication, or maybe I should say xaml duplication.

One of the things I did after the first two parts of this series is to add some more projects that I would need once wired up and ready to continue with other parts of the project.  First I added the respective test projects, the other Silverlight Module projects etc.

This brings me to one of the differences between the WPF and Silverlight Interfaces.  For the modules that will be used in the Silverlight Project you?ll need to add Silverlight Class Library Project as shown to the left.  The Silverlight Class Library Template adds various assemblies and other references that are needed for these modules to be used in Silverlight Applications.

At this time I added a project to match each of the WPF Modules I had added previously.  I created four, then basically created the exact same presenters and views for the Silverlight Module.  After all of this I ended up with the following solution explorer view ? check the image to the right.

The second differences is in the shells and boot strappers.

In the WPF application the shell has the following simple code to kick off of the shell.  I used ReSharper to remove the unnecessary assemblies and other references.

[sourcecode language=”csharp”]
using System.Windows;

namespace HighBall.Interface.Wpf
{
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var bootstrapper = new HighBallBootStrapper();
bootstrapper.Run();
}
}
}
[/sourcecode]

What I ended up with was simple an OnStartup method overriding the Application Class method.  In this method is simply the base class call, instantiation, and the Run method to kick off the boot strapper.  This is very different then the slew of code needed for the Silverlight application bootstrapper startup.  Now keep in mind that most of this code is generated when you create the Silverlight Application.

[sourcecode language=”csharp”]
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Browser;

namespace HighBall.Interface.Silverlight
{
public partial class App : Application
{
public App()
{
Startup += Application_Startup;
Exit += Application_Exit;
UnhandledException += Application_UnhandledException;

InitializeComponent();
}

private void Application_Startup(object sender, StartupEventArgs e)
{
var bootstrapper = new HighBallBootStrapper();
bootstrapper.Run();
}

private void Application_Exit(object sender, EventArgs e)
{
}

private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
if (!Debugger.IsAttached)
{
e.Handled = true;
Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
}
}

private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
{
try
{
string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
errorMsg = errorMsg.Replace(‘"’, ‘\”).Replace("\r\n", @"\n");

HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight 2 Application " + errorMsg +
"\");");
}
catch (Exception)
{
}
}
}
}
[/sourcecode]

The only method that is really altered is the Application_Startup method.  Simply instantiate the boot strapper and call run.

Now that we have that take a look at the boot strappers themselves.  They each have some respective differences.  The WPF bootstrapper looks like this:

[sourcecode language=”csharp”]
using System.Windows;
using HighBall.Interface.Modules.Schedule;
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Composite.UnityExtensions;

namespace HighBall.Interface.Wpf
{
internal class HighBallBootStrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
var shell = new HighBallShell();
return shell;
}

protected override IModuleCatalog GetModuleCatalog()
{
var catalog = new ModuleCatalog();
catalog.AddModule(typeof(ScheduleAddPresenter));
return catalog;
}
}
}
[/sourcecode]

The Silverlight bootstrapper is below:

[sourcecode language=”csharp”]
using System.Windows;
using HighBall.Interface.Modules.Schedule.Silverlight;
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Composite.UnityExtensions;

namespace HighBall.Interface.Silverlight
{
public class HighBallBootStrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
var shell = Container.Resolve();
Application.Current.RootVisual = shell;
return shell;
}

protected override IModuleCatalog GetModuleCatalog()
{
var catalog = new ModuleCatalog();
catalog.AddModule(typeof(ScheduleAddPresenter));
return catalog;
}
}
}
[/sourcecode]

The one difference as one can see is the Silverlight Application sets the Application.Current.RootVisual to the application shell.  Again, one of those places that just screams code duplication.  That?s it.

In my next entry I’m going to do a real quick wrap up and then post the code for what I?ve worked through so far.

HighBall Part Duex (#02) Adding the Composite Application Libraries

Navigation of Highball Series Part #1 | Part #2 | Part #3 | Part #4

The first thing I did was go download the Composite Application Library Guidance.  The Patterns & Practices Group Page on the Composite Application Library is available also with more links and information.  The steps I took to get all the CAL stuff added went something like this.

  • I added the projects & test projects for;  Composite.Desktop, Composite.Desktop.Tests, Composite.Presentation.Desktop, Composite.Presentation.Desktop.Tests, Composite.UnityExtensions.Desktop, Composite.UnityExtensions.Desktop.Tests.
  • Then I added the Microsoft.Practices.ServiceLocation.dll to the 3rd Party Assemblies directory and fixed the references in the above projects.  Since I had literally copied them from the CAL directory that the installer places them, I had to fix up the references, but I had done so on purpose so that I’d know exactly what references what.

After adding that I setup a project for my first module named HighBall.Interface.Modules.ScheduleModule.  In this module I made a view called ScheduleAddView.xaml and a module called ScheduleAddModule.cs.  In the xaml view I added the following markup, which is identical to the markup I created for the ScheduleAdd.xaml in the previous blog post.

[sourcecode language=”xml”]
<UserControl x:Class="HighBall.Interface.Modules.ScheduleModule.Views.ScheduleAdd"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
Foreground="White" Background="Black">
<Grid x:Name="LayoutRoot" Background="Black">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Margin="5,5,5,5" x:Name="textRoutes">Routes:</TextBlock>
<ListBox Margin="5,5,5,5" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ListBoxItem x:Name="routeOne" Content="WES Commuter Rail"></ListBoxItem>
<ListBoxItem x:Name="routeTwo" Content="9 Powell"></ListBoxItem>
<ListBoxItem x:Name="routeThree" Content="72 Killingsworth/82nd Ave"></ListBoxItem>
<ListBoxItem x:Name="routeFour" Content="590 Tacoma/Seattle"></ListBoxItem>
<ListBoxItem x:Name="routeFive" Content="Sounder Commuter Rail"></ListBoxItem>
<ListBoxItem x:Name="routeSix" Content="The Newark Light Rail Orange Line"></ListBoxItem>
<ListBoxItem x:Name="routeSeven" Content="The Newark Light Rail Blue Line"></ListBoxItem>
<ListBoxItem x:Name="routeEight" Content="The River Line"></ListBoxItem>
</ListBox>
<TextBlock x:Name="routeName" Margin="0,5,5,5" Grid.Column="1" Grid.Row="0" >Add New Schedule</TextBlock>
<StackPanel Grid.Column="1" Grid.Row="1" >
<TextBlock x:Name="frequencyIdentifier" Margin="0,5,5,0" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top">Frequency Identifier</TextBlock>
<TextBox x:Name="textFrequencyIdentifier" Margin="0,5,5,0" Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Stretch" VerticalAlignment="Top" Text=""></TextBox>
<TextBlock x:Name="startLocation" Margin="0,5,5,0" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top">Start Location</TextBlock>
<TextBox x:Name="textStartLocation" Margin="0,5,5,0" Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Stretch" VerticalAlignment="Top" Text=""></TextBox>
<TextBlock x:Name="startTime" Margin="0,5,5,0" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top">Start Time</TextBlock>
<TextBox x:Name="textStartTime" Margin="0,5,5,0" Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Stretch" VerticalAlignment="Top" Text=""></TextBox>
<TextBlock x:Name="endLocation" Margin="0,5,5,0" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top">End Location</TextBlock>
<TextBox x:Name="textEndLocation" Margin="0,5,5,0" Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Stretch" VerticalAlignment="Top" Text=""></TextBox>
<TextBlock x:Name="endTime" Margin="0,5,5,0" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top">End Time</TextBlock>
<TextBox x:Name="textEndTime" Margin="0,5,5,0" Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Stretch" VerticalAlignment="Top" Text=""></TextBox>
<TextBlock x:Name="scheduleStarts" Margin="0,5,5,0" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Top">Schedule Starts</TextBlock>
<TextBox x:Name="textScheduleStarts" Margin="0,5,5,0" Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Stretch" VerticalAlignment="Top" Text=""></TextBox>
<TextBlock x:Name="scheduleEnds" Margin="0,5,5,0" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top">Schedule Ends</TextBlock>
<TextBox x:Name="textScheduleEnds" Margin="0,5,5,0" Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Stretch" VerticalAlignment="Top" Text=""></TextBox>
<Button x:Name="buttonAddNewSchedule" Margin="10,10" Grid.Column="1" Grid.Row="1" Height="Auto" Width="Auto" HorizontalAlignment="Right" VerticalAlignment="Top" Content="Add Schedule"></Button>
</StackPanel>
</Grid>
</UserControl>
[/sourcecode]

In the code behind and the class file I added nothing at this time.  We?ll come back to that in a minute.

Once I created that I went back to the HighBall.Interface.Wpf project that I had created in the previous blog entry.  I then added a HighBallBootStrapper.cs class file to the project.  In that file I added the following code.

[sourcecode language=”csharp”]
using System.Windows;
using HighBall.Interface.Modules.ScheduleModule;
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Composite.UnityExtensions;

namespace HighBall.Interface.Wpf
{
class HighBallBootStrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
var shell = new HighBallShell();
shell.Show();
return shell;
}
protected override IModuleCatalog GetModuleCatalog()
{
var catalog = new ModuleCatalog()
.AddModule(typeof (ScheduleAddModule));
return catalog;
}
}
}
[/sourcecode]

In the code behind of the App.xaml file I then added the following.

[sourcecode language=”csharp”]
using System.Windows;
namespace HighBall.Interface.Wpf
{
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var bootstrapper = new HighBallBootStrapper();
bootstrapper.Run();
}
}
}
[/sourcecode]

Now that we?re wired up there, we move on to the last few steps.  The next step is to wire the module up so it will show up in the shell when it is launched.  So open up the ScheduleAddModule.cs class file and add the following code.

[sourcecode language=”csharp”]
using HighBall.Interface.Modules.ScheduleModule.Views;
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Composite.Regions;
namespace HighBall.Interface.Modules.ScheduleModule
{
public class ScheduleAddModule : IModule
{
private readonly IRegionViewRegistry regionViewRegistry;
public ScheduleAddModule(IRegionViewRegistry registry)
{
regionViewRegistry = registry;
}

public void Initialize()
{
regionViewRegistry.RegisterViewWithRegion("HighBallMainRegion", typeof(ScheduleAddView));
}
}
}
[/sourcecode]

Before wrapping up I went ahead and added the remaining view into the module project that is still in the HighBall.Interface.Wpf project.  Now I have the ScheduleViewAll.xaml view in the HighBall.Interface.Modules.ScheduleModule project.  Just to make sure all the associations where correct I actually made the file and THEN copied all of the xaml into the new file.  That way everything gets generated correctly.

I did run into an odd scenario during working through this example.  I launched the application and everything showed up as it is supposed to, BUT, two application screens would pop up.  I fiddled around a bit more and ended up with a blank screen with my injection broken.  Eventually I got it working but it was really odd regardless.

In my next entry I’ll be getting into describing the nuts and bolts of what is going on so far to provide some context.