I can think only a simple two level ItemsControl(ListBox) solution for this. And the inner visual element can be a Styled CheckBox to look like 'O' or 'X' here is the sample I just made for you . Of course you do need to a DateHeader collection at the top aligned with the checkboxes.
alt text http://img339.imageshack.us/img339/8695/grid.jpg
XAML
<UserControl.Resources>
<DataTemplate x:Key="CellTemplate">
<Grid Width="25" Height="25">
<CheckBox IsChecked="{Binding IsPresent}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
<DataTemplate x:Key="RowTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Margin="4,0,0,0" Text="{Binding Name}" TextWrapping="Wrap"/>
<ItemsControl ItemsSource="{Binding WorkingDays}" HorizontalAlignment="Left" VerticalAlignment="Top" ItemTemplate="{StaticResource CellTemplate}" Grid.Column="1" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</DataTemplate>
</UserControl.Resources>
<ItemsControl x:Name="lstWorkingDaysMain" ItemsSource="{Binding}" ItemTemplate="{StaticResource RowTemplate}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
C#
public class Student
{
public Student()
{
WorkingDays = new List<WorkingDay>();
}
public string Name { get; set; }
public List<WorkingDay> WorkingDays { get; set; }
}
public class WorkingDay
{
public bool IsPresent{get; set;}
public DateTime Date { get; set; }
}
And the test data population at the code behind xaml.cs
List<Student> students = new List<Student>();
Student student = new Student() { Name = "Aaaaaa" };
student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,5), IsPresent=true} );
student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,6), IsPresent=true} );
student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,7), IsPresent=true} );
student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,8), IsPresent=true} );
student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,9), IsPresent=true} );
student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,10), IsPresent=true} );
student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,11), IsPresent=true} );
student.WorkingDays.Add(new WorkingDay() { Date=new DateTime(2009,5,12), IsPresent=true} );
students.Add(student);
student = new Student() { Name = "Bbbbbb" };
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 5), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 6), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 7), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 8), IsPresent = false });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 9), IsPresent = false });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 10), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 11), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 12), IsPresent = true });
students.Add(student);
student = new Student() { Name = "Cccccc" };
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 5), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 6), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 7), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 8), IsPresent = false });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 9), IsPresent = false });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 10), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 11), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 12), IsPresent = false });
students.Add(student);
student = new Student() { Name = "Dddddd" };
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 5), IsPresent = false });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 6), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 7), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 8), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 9), IsPresent = false });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 10), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 11), IsPresent = true });
student.WorkingDays.Add(new WorkingDay() { Date = new DateTime(2009, 5, 12), IsPresent = true });
students.Add(student);
this.DataContext = students;
Best Answer
Silverlight doesn't have much binary serialization built in; however, protobuf-net works on Silverlight and may help plug this gap. In the current build you can only really serialize types you control (due to adding attributes) - however, I'm in the middle of a big refactor to (among other things) add support for serializing types without attributes.
I expect it to be about 2 more weeks before this is available as a (hopefully) stable build, but you're welcome to take a look at it then.
Note that you will still need to give it some help (telling it what you want it to serialize), but it may be useful.
In particular, the data format ("protocol buffers") is designed to be both dense and efficient to process, which should increase the parse speed. See here for more (numbers are from main .NET, not Silverlight)