XAML renders differently

I was reading with great interest Keith's posts about creating a color chart in ASP.NET and decided to roll out a similar WPF application in pure code first - in Boo ofcourse -  and in XAML second. The former will be a Windows application and the latter will be an XBAP application so I can run it inside a browser - just like Keith's demo. 

The motivation for this came about when I realized that the color chart can easily be rendered using the WPF ListBox.  The trick was to set the ItemsPanel property of the ListBox to a template containing a WPF UniformGrid.

Coding the windows version in Boo was a breeze.  All in all it took only about 20 minutes to get it up and running since Keith had mapped the whole thing already. I used Keith's original method of using Reflection to get the list of predefined colors and adapted it for WPF. 

    class ColorService:
	static def GetBrushes() as System.Collections.IEnumerable:
		for propertyInfo as PropertyInfo in typeof(Brushes).GetProperties():
			memberInfo = cast(MemberInfo, propertyInfo)
			brush = cast(Brush,propertyInfo.GetValue(null,null))
			yield NamedBrush(memberInfo.Name, brush)
			
	class NamedBrush:
		[getter(Name)] _name as string
		[getter(Brush)] _brush as Brush
		
		def constructor(name as string, brush as Brush):
			_name = name
			_brush = brush
	
		override def ToString():
			return _name

Here's the c# version:

   
    public class ColorService
    {
        static public IEnumerable GetBrushes()
        {
            foreach (PropertyInfo propertyInfo in typeof(Brushes).GetProperties())
            {
                MemberInfo memberInfo = (MemberInfo)propertyInfo;
                Brush brushValue = (Brush)propertyInfo.GetValue(null, null);
                yield return new NamedBrush(memberInfo.Name, brushValue);
            }
        }

        public class NamedBrush
        {
            public NamedBrush(string name, Brush brush)
            {
                _name = name;
                _brush = brush;
            }

            public string Name
            {
                get { return _name; }
            }

            public Brush Brush
            {
                get { return _brush; }
            }

            public override string ToString()
            {
                return _name;
            }

            string _name;
            Brush _brush;
        }
    }

Here's how the windows app looks like:

Color Chart Demo

Now converting the app into XBAP took quite some time to finish since I'm not well versed in XAML yet. I had to check the Boo layout code repeatedly to get the XAML finally working.  Heres the XAML layout code:

<Page x:Class="ColorChart.Page1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Page1"
    >
    <Page.Resources>
        <Style x:Key="CCStyle" >
            <Setter Property="Control.BorderBrush" Value="LightGray"/>
            <Setter Property="Control.BorderThickness" Value="1"/>
            <Setter Property="Control.Margin" Value="3"/>
        </Style>
        <ItemsPanelTemplate x:Key="CCPanel">
            <UniformGrid Columns="6"></UniformGrid>
        </ItemsPanelTemplate>
        <DataTemplate x:Key="CCTemplate">
            <StackPanel>
                <Rectangle     
                    Width="100" 
                    Height="40" 
                    Fill="{Binding Path=Brush}" 
                    HorizontalAlignment="Left"/>
                <TextBlock 
                    FontSize="11" 
                    Text="{Binding Path=Name}" 
                    HorizontalAlignment="Center">
                </TextBlock>
            </StackPanel>
        </DataTemplate>
    </Page.Resources>
    <ListBox 
        Name="listBox1" 
        SelectionMode="Single" 
        ItemsPanel="{StaticResource CCPanel}" 
        ItemTemplate="{StaticResource CCTemplate}" 
        ItemContainerStyle="{StaticResource CCStyle}"/>
</Page>

This is the c# code-behind for the XAML above:

namespace ColorChart
{
    public partial class Page1 : System.Windows.Controls.Page
    {
        public Page1()
        {
            InitializeComponent();
            this.listBox1.ItemsSource = ColorService.GetBrushes();
        }
    }
}

And here's the layout code in Boo which does thesame thing as the XAML above:

class CCStyle(Style):
    def constructor():
        s1 = Setter(ListBoxItem.BorderThicknessProperty, Thickness(1))
        s2 = Setter(ListBoxItem.MarginProperty, Thickness(3))
        s3 = Setter(ListBoxItem.BorderBrushProperty, Brushes.LightGray)
        s4 = Setter(ListBoxItem.HorizontalAlignmentProperty, HorizontalAlignment.Center)
        self.Setters.Add(s1)
        self.Setters.Add(s2)
        self.Setters.Add(s3)
        self.Setters.Add(s4)

class CCPanel(ItemsPanelTemplate):
    def constructor():
        root = FrameworkElementFactory(UniformGrid)
        root.SetValue(UniformGrid.ColumnsProperty, 6)
        self.VisualTree = root

class CCTemplate(DataTemplate):
    def constructor():
        root = FrameworkElementFactory(StackPanel)
        ch1 = FrameworkElementFactory(Rectangle)
        ch1.SetValue(Rectangle.WidthProperty, 100.0)
        ch1.SetValue(Rectangle.HeightProperty, 40.0)
        ch1.SetValue(Rectangle.FillProperty, Binding("Brush"))
        ch2 = FrameworkElementFactory(TextBlock)
        ch2.SetValue(TextBlock.TextProperty, Binding("Name"))
        ch2.SetValue(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Center)
        root.AppendChild(ch1)
        root.AppendChild(ch2)
        self.VisualTree = root
        
class ColorChartView(ListBox):
    def constructor():
        ItemContainerStyle = CCStyle()
        ItemsPanel = CCPanel()
        ItemTemplate = CCTemplate()
        ItemsSource = ColorService.GetBrushes()        

An XBAP application needs to be compiled and then published to an IIS server first.  After you have done that open your IE browser - or Firefox browser if you have the  IE Tab extension installed - and type in the url of your application.  In my case I typed in http://localhost/winfx/colorchart.xbap and here's what came out:

Color Chart XBAP Demo

Now that was neat. The keyboard navigation and mouse selection works just like in the windows version. But if you will look at it more closely you'll notice that there's something different about the XAML rendered view.

XAML by the way is tokenized into BAML during compilation and is embedded as a resource inside the executable file. Maybe the XAML team needs more time to tweak their engine.

Published 09-30-2006 12:28 AM by smash
Filed under: , , , ,

Comments

# re: XAML renders differently@ Friday, September 29, 2006 8:09 PM

great example smash! two thumbs up! :)

# re: XAML renders differently@ Saturday, September 30, 2006 5:46 AM

i'm glad you liked the WPF version keith! i have a feeling those who do asp.net apps like you would be able to relate to XAML. :)  

by smash

# re: XAML renders differently@ Saturday, September 30, 2006 10:31 AM

i'm currently experimenting in XAML too but haven't had the time to post about it since i'm still stuck with .NET 2.0 apps. Probably in the next year or two we could start rolling out applications using this technology.