Does my code demonstrate good WPF practice?

I would say, no, you're not going about this the right way. You're doing too much of the work and letting WPF do too little. You should be using data binding and an ItemsControl, and let WPF do all the heavy lifting of figuring out where to put things and what to put in them.

  1. I used an XmlDataProvider in this example because it's the easiest way to demonstrate how data-binding can be used without writing code. You'd probably build a view model class that exposed a collection of objects with Name and Date properties and bind to an instance of that.

  2. Using Canvas and pixel-by-pixel layouts is a Bad Thing in WPF, which is all about building resolution-independent UIs. It's much better to make the layout engine do all that work.

  3. Not everything that looks like a grid needs to be laid out with the Grid. There's much, much less XAML if you lay this grid out as a horizontal StackPanel. This keeps you from having to screw around with row and column numbers. The only reason my layout uses a Grid is to make the border size to its content.

Here's my rework of what you provided. To my eye the result looks pretty much identical to yours, but it's about half as much XAML (not counting the brushes) and it's way easier to modify.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Background="{DynamicResource NormalBrush}">

  <Page.Resources>
       <XmlDataProvider x:Key="Days" XPath="Days">
        <x:XData>
          <Days xmlns="">
            <Day Name="Sunday" Date="03/14/2010"/>
            <Day Name="Monday" Date="03/15/2010"/>
            <Day Name="Tuesday" Date="03/16/2010"/>
            <Day Name="Wednesday" Date="03/17/2010"/>
            <Day Name="Thursday" Date="03/18/2010"/>
            <Day Name="Friday" Date="03/19/2010"/>
            <Day Name="Saturday" Date="03/20/2010"/>
          </Days>
        </x:XData>
       </XmlDataProvider>

        <LinearGradientBrush x:Key="NormalBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Offset="1.0" Color="White"/>
                    <GradientStop Offset="0.0" Color="LightSlateGray"/>
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>

        <LinearGradientBrush x:Key="DayHeaderBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Offset="0.0" Color="Peru" />
                    <GradientStop Offset="1.0" Color="White" />
                </GradientStopCollection>
            </GradientBrush.GradientStops>
        </LinearGradientBrush>        

  </Page.Resources>
        <Grid Margin="50">
          <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>            
          </Grid.RowDefinitions>
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
          </Grid.ColumnDefinitions>
          <StackPanel Orientation="Horizontal">
            <ItemsControl ItemsSource="{Binding Source={StaticResource Days}, XPath=Day}">
              <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                  <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
              </ItemsControl.ItemsPanel>
              <ItemsControl.ItemTemplate>
                <DataTemplate>
                <StackPanel Orientation="Vertical" Background="White">
                    <Border BorderBrush="Black" BorderThickness="1,1,0,0" Background="{StaticResource DayHeaderBrush}">
                      <TextBlock Margin="30,10" HorizontalAlignment="Center" Text="{Binding XPath=@Name}"/>
                    </Border>
                    <Border BorderBrush="Black" BorderThickness="1,1,0,0">
                      <TextBlock Margin="30,10" Height="50" HorizontalAlignment="Center" Text="{Binding XPath=@Date}"/>
                    </Border>
                  </StackPanel>
                </DataTemplate>
              </ItemsControl.ItemTemplate>
            </ItemsControl>
            <Border BorderBrush="Black" BorderThickness="0,0,1,0"/>
          </StackPanel>
        </Grid>
</Page>

I don't know how big your project is going to be, but the biggest tip I can give you when starting WPF is to look into the PRISM framework:

http://www.codeplex.com/CompositeWPF

http://msdn.microsoft.com/en-us/magazine/cc785479.aspx

It's an excellent framework, and solves a lot of problems for you.

Regarding your calendar, I would recommend making it a re-usable look-less control, this article may help you:

http://www.codeproject.com/KB/WPF/WPFOutlookCalendar.aspx


You can follow the MVVM pattern if you later decide to use binding. For more details:

http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

You can use the 'RelayCommand' to go to the next day if you want to show the appointments separately for each day.

Tags:

C#

Wpf