Well, I just got around to writing my first Longhorn application and I forgot how great it feels to be researching such new technology. I didn't want to do the typical Hello World application so I set off to see if I could come close to emulating the Mac “Candy Blue” interface look. First I started with a basic xaml file with one table in it:
<Window
xmlns="http://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
def:Class="Application1.Window1"
def:CodeBehind="Window1.xaml.cs"
Text="Hello World" Visible="True"
Loaded="WindowLoaded"
>
<FlowPanel Margin="10">
<Border Background="#000000" BorderBrush="#000000" BorderThickness="1">
<Table CellSpacing="0">
<Column Width="20" />
<Column Width="300" />
<Column Width="80" />
<Column Width="90%" />
<Header>
<Row>
<Cell></Cell>
<Cell>Song Name</Cell>
<Cell>Time</Cell>
<Cell>Artist</Cell>
</Row>
</Header>
<Body>
<Row Background="#edf3fe">
<Cell></Cell>
<Cell>Down to the Nightclub</Cell>
<Cell>3:57</Cell>
<Cell>Tower of Power</Cell>
</Row>
<Row Background="#ffffff">
<Cell></Cell>
<Cell>Chameleon</Cell>
<Cell>7:33</Cell>
<Cell>Herbie Hancock And The Head Hunters</Cell>
</Row>
<Row Background="#edf3fe">
<Cell></Cell>
<Cell>How Do Y'All Know</Cell>
<Cell>3:45</Cell>
<Cell>Harry Connick, Jr.</Cell>
</Row>
<Row Background="#ffffff">
<Cell></Cell>
<Cell>Diggin' on James Brown</Cell>
<Cell>4:21</Cell>
<Cell>Tower of Power</Cell>
</Row>
</Body>
</Table>
</Border>
</FlowPanel>
</Window>
After creating this basic table, the next step was to emulate the candy style of the Mac. For a normal header, I was able to come pretty close by using the following LinearGradientBrush:
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#ffffff" Offset="0" />
<GradientStop Color="#efefef" Offset="0.49" />
<GradientStop Color="#e8e8e8" Offset="0.5" />
<GradientStop Color="#f0f0f0" Offset="0.51" />
<GradientStop Color="#ffffff" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
For a selected header, I use the following LinearGradientBrush:
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#b8faff" Offset="0" />
<GradientStop Color="#75b3f0" Offset="0.49" />
<GradientStop Color="#5999e5" Offset="0.5" />
<GradientStop Color="#87b8ea" Offset="0.51" />
<GradientStop Color="#d0e0f4" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
When adding the brush to the background for the headers, the final program looks like this:
<Window
xmlns="http://schemas.microsoft.com/2003/xaml"
xmlns:def="Definition"
def:Class="Application1.Window1"
def:CodeBehind="Window1.xaml.cs"
Text="Hello World" Visible="True"
Loaded="WindowLoaded"
>
<FlowPanel Margin="10">
<Border Background="#000000" BorderBrush="#000000" BorderThickness="1">
<Table CellSpacing="0">
<Column Width="20" />
<Column Width="300" />
<Column Width="80" />
<Column Width="90%" />
<Header>
<Row>
<Cell>
<Cell.Background>
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#ffffff" Offset="0" />
<GradientStop Color="#efefef" Offset="0.49" />
<GradientStop Color="#e8e8e8" Offset="0.5" />
<GradientStop Color="#f0f0f0" Offset="0.51" />
<GradientStop Color="#ffffff" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Cell.Background>
</Cell>
<Cell>
<Cell.Background>
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#b8faff" Offset="0" />
<GradientStop Color="#75b3f0" Offset="0.49" />
<GradientStop Color="#5999e5" Offset="0.5" />
<GradientStop Color="#87b8ea" Offset="0.51" />
<GradientStop Color="#d0e0f4" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Cell.Background>
Song Name
</Cell>
<Cell>
<Cell.Background>
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#ffffff" Offset="0" />
<GradientStop Color="#efefef" Offset="0.49" />
<GradientStop Color="#e8e8e8" Offset="0.5" />
<GradientStop Color="#f0f0f0" Offset="0.51" />
<GradientStop Color="#ffffff" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Cell.Background>
Time
</Cell>
<Cell>
<Cell.Background>
<LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#ffffff" Offset="0" />
<GradientStop Color="#efefef" Offset="0.49" />
<GradientStop Color="#e8e8e8" Offset="0.5" />
<GradientStop Color="#f0f0f0" Offset="0.51" />
<GradientStop Color="#ffffff" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Cell.Background>
Artist
</Cell>
</Row>
</Header>
<Body>
<Row Background="#edf3fe">
<Cell></Cell>
<Cell>Down to the Nightclub</Cell>
<Cell>3:57</Cell>
<Cell>Tower of Power</Cell>
</Row>
<Row Background="#ffffff">
<Cell></Cell>
<Cell>Chameleon</Cell>
<Cell>7:33</Cell>
<Cell>Herbie Hancock And The Head Hunters</Cell>
</Row>
<Row Background="#edf3fe">
<Cell></Cell>
<Cell>How Do Y'All Know</Cell>
<Cell>3:45</Cell>
<Cell>Harry Connick, Jr.</Cell>
</Row>
<Row Background="#ffffff">
<Cell></Cell>
<Cell>Diggin' on James Brown</Cell>
<Cell>4:21</Cell>
<Cell>Tower of Power</Cell>
</Row>
</Body>
</Table>
</Border>
</FlowPanel>
</Window>
Take a gander and see what you think. I know there's a lot more work to do to make it look more like iTunes but it should be fun getting there. The next step I figure is to get the background brushes ripped into a Style and use the Style tag. Once that is done, perhaps I will investigate data-binding and see if I can't get this sucker running off of a database.
Since this was my first Longhorn app, I ran into a couple of obstacles that I thought I would blog about. The naming conventions still seem kind of off in the new Avalon libraries. For example, to set the left and top coordinates of a Rectangle, you use RectangleLeft and RectangleTop. However, when using the Canvas, you would use Canvas.Left and Canvas.Top. Since this is such an early build, I'm sure this kind of thing will be ironed out in the future.
Being an HTML developer, it takes some getting used to using “Decorators“ instead of properties. For example, to give a table a border, you do not set a border property, you surround the table with a Border decorator. This convention I do really like. It's really great to see such use of design patterns in the new avalon namespace.
Funny Documentation Moment of the Evening: Running into a class called “HackBorder“ whose documentation simply reads “Do not use.“.
Feel free to let me know what you think.