Deborah's Developer MindScape






         Tips and Techniques for Web and .NET developers.

November 23, 2009

Silverlight: Building a Grid and StackPanel in Code

Filed under: C#,Silverlight,VB.NET @ 2:11 am

Many Silverlight examples show how to build controls with XAML. But XAML does not support programming logic. So sometimes you need to build the controls with real code in C# or VB. This example demonstrates how to build a Grid and StackPanel with Buttons first in XAML and then in C# and VB.

It seems that there would be a relatively straightforward set of rules to "convert" XAML into C# or VB code. And there is, sort of. But these rules break down in some cases. Hopefully this is just because XAML is still relatively new and these inconsistencies will be corrected over time.

A common scenario in building Silverlight applications is to divide the layout into areas that contain a header, menu, contents, and so on. In this example, the layout simply contains a set of buttons.

Here the buttons are on the top:

image

In XAML:

<UserControl x:Class="SilverlightApplication1.MainPage"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Grid x:Name="LayoutRoot">
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" 
                    Background="Bisque">
            <Button Content="Home" Margin="10,10,0,0"/>
            <Button Content="Customers" Margin="10,10,0,0"/>
            <Button Content="Sales" Margin="10,10,0,0"/>
        </StackPanel>
    </Grid>
</UserControl>

This layout includes a basic grid that is the layout for the entire UserControl. The grid has two row definitions: one for a menu bar that is automatically sized to the size of the buttons and the other for content area sized to the remainder of the page. A StackPanel within the grid contains the set of three buttons.

But lets say that this feature needs to be implemented in C# or VB code instead. So the XAML code is limited to the very basics:

<UserControl x:Class="SilverlightApplication1.MainPage"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Grid x:Name="LayoutRoot">
     <!—Generated in code –>    
  </Grid>
</UserControl>

In the code, the first thing to do is create the row definitions.

In C#:

RowDefinition rd;
rd = new RowDefinition {
    Height = GridLength.Auto};
LayoutRoot.RowDefinitions.Add(rd);
rd = new RowDefinition {
    Height = new GridLength(1, GridUnitType.Star)};
LayoutRoot.RowDefinitions.Add(rd);

In VB:

Dim rd As New RowDefinition
rd = New RowDefinition With { _
        .Height = GridLength.Auto}
LayoutRoot.RowDefinitions.Add(rd)
rd = New RowDefinition With { _
        .Height = New GridLength(1, GridUnitType.Star)}
LayoutRoot.RowDefinitions.Add(rd)

This code creates a new RowDefinition, adds it to the list of RowDefinitions for the Grid named LayoutRoot.

For the first row definition the code uses the GridLength.Auto property. This ensures that the row is sized automatically based on the controls within the grid.

The second row definition uses the GridLength constructor to define the "*" value. The "*" value is a weighted proportion of available space. The "*" requires the constructor to define both a value (the proportion) and the type (GridUnitType.Star). Since this example only has one row to fill, the value is set to 1.

If there were two rows to fill whereby one row was to take 80% of the remaining area and the other row 20%, the constructor parameters would be GridLength(80, GridUnitType.Star) and GridLength(20, GridUnitType.Star) respectively.

The next step is to create the StackPanel. This example uses a horizontal orientation and a Bisque background color.

In C#:

StackPanel sp = new StackPanel();
sp.Orientation = Orientation.Horizontal;
sp.Background = new SolidColorBrush(Color.FromArgb(0xFF, 0xFF,
                                                   0xE4, 0xC4));
LayoutRoot.Children.Add(sp);

In VB:

Dim sp As New StackPanel
sp.Orientation = Orientation.Horizontal
sp.Background = New SolidColorBrush(Color.FromArgb(&HFF, &HFF, _
                                                   &HE4, &HC4))
LayoutRoot.Children.Add(sp)

This code creates the StackPanel. It then sets its Orientation and Background. Finally, it adds it to the children collection for the LayoutRoot grid. This places the StackPanel within the UserControl grid.

This example points out one of the inconsistencies in converting the code from XAML to C# or VB: Color values.

XAML has a set of about 141 colors where C# and VB only have 16.

There are color charts (including this one here) that provide the Hexadecimal color values of the XAML predefined colors. For this example, Bisque converts to #FFFFE4C4.

Finally, the buttons are added to the StackPanel with this code.

In C#:

Button btn;
btn = new Button  { 
        Content = "Home", 
        Margin = new Thickness(10, 10, 0, 0)};
sp.Children.Add(btn);
btn = new Button  { 
        Content = "Customers", 
        Margin = new Thickness(10, 10, 0, 0)};
sp.Children.Add(btn);
btn = new Button  { 
        Content = "Sales", 
        Margin = new Thickness(10, 10, 0, 0)};
sp.Children.Add(btn);

In VB:

Dim btn As Button
btn = New Button With { _
        .Content = "Home", _
        .Margin = New Thickness(10, 10, 0, 0)}
sp.Children.Add(btn)
btn = New Button With { _
        .Content = "Customers", _
        .Margin = New Thickness(10, 10, 0, 0)}
sp.Children.Add(btn)
btn = New Button With { _
        .Content = "Sales", _
        .Margin = New Thickness(10, 10, 0, 0)}
sp.Children.Add(btn)

This code adds three buttons to the StackPanel. For each Button, the Content string and Margin are set. The Button is then added to the children collection for the StackPanel.

Here the buttons are along the left:

image

In XAML:

<UserControl x:Class="SilverlightApplication1.MainPage"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Grid x:Name="LayoutRoot">
            <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <StackPanel Orientation="Vertical" Background="Bisque" >
            <Button Content="Home" Margin="10,10,0,0"/>
            <Button Content="Customers" Margin="10,10,0,0"/>
            <Button Content="Sales" Margin="10,10,0,0" />
        </StackPanel>
    </Grid>
</UserControl>

In C#:

public MainPage()
{
    InitializeComponent();
    Loaded += new RoutedEventHandler(MainPage_Loaded);
}

private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    ColumnDefinition cd ;
    cd = new ColumnDefinition {
            Width = GridLength.Auto};
    LayoutRoot.ColumnDefinitions.Add(cd);
    cd = new ColumnDefinition {
            Width = new GridLength(1, GridUnitType.Star)};
    LayoutRoot.ColumnDefinitions.Add(cd);

    StackPanel sp = new StackPanel(); 
    sp.Orientation = Orientation.Vertical;
    sp.Background = new SolidColorBrush(Color.FromArgb(0xFF, 0xFF,
                                                       0xE4, 0xC4));
    LayoutRoot.Children.Add(sp);

    Button btn;
    btn = new Button  {
            Content = "Home",
            Margin = new Thickness(10, 10, 0, 0)};
    sp.Children.Add(btn);
    btn = new Button  {
            Content = "Customers",
            Margin = new Thickness(10, 10, 0, 0)};
    sp.Children.Add(btn);
    btn = new Button  {
            Content = "Sales",
            Margin = new Thickness(10, 10, 0, 0)};
    sp.Children.Add(btn);
}

In VB:

Public Sub New()
    InitializeComponent()
End Sub

Private Sub MainPage_Loaded(ByVal sender As Object,  _
   ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

    Dim cd As ColumnDefinition
    cd = New ColumnDefinition With { _
            .Width = GridLength.Auto}
    LayoutRoot.ColumnDefinitions.Add(cd)
    cd = New ColumnDefinition With { _
            .Width = New GridLength(1, GridUnitType.Star)}
    LayoutRoot.ColumnDefinitions.Add(cd)

    Dim sp As New StackPanel
    sp.Orientation = Orientation.Vertical
    sp.Background = New SolidColorBrush(Color.FromArgb(&HFF, &HFF, 
                                                       &HE4, &HC4))
    LayoutRoot.Children.Add(sp)

    Dim btn As Button
    btn = New Button With { _
            .Content = "Home", _
            .Margin = New Thickness(10, 10, 0, 0)}
    sp.Children.Add(btn)
    btn = New Button With { _
            .Content = "Customers", _
            .Margin = New Thickness(10, 10, 0, 0)}
    sp.Children.Add(btn)
    btn = New Button With { _
            .Content = "Sales", _
            .Margin = New Thickness(10, 10, 0, 0)}
    sp.Children.Add(btn)
End Sub

This code is nearly identical to the prior code. It demonstrates ColumnDefinitions instead of RowDefinitions and orients the StackPanel vertically.

Use these techniques any time you need to create Column or Row Definitions in code. Or if you need to create a StackPanel or Buttons in code.

Enjoy!

4 Comments

  1.   Steve — December 3, 2009 @ 10:41 am    Reply

    you havn’t shown how to put a control in a grid row in code?

  2.   Hamza — October 28, 2010 @ 6:45 am    Reply

    Here is how to add lets say a stackpanel to a grid row and column

    sp = new StackPanel();

    //Set the stack panel’s grid.row and grid.column property like this

    sp.SetValue(Grid.ColumnProperty,0);
    sp.SetValue(Grid.RowProperty,0);

    LayoutRoot.Children.Add(sp);

  3.   Frank — November 16, 2011 @ 12:20 pm    Reply

    The selecting the row or column doesn’t work for me. I have two columns and using the above code to set to the second column (sp.SetValue(Grid.ColumnProperty,1);) leaves the object in the first column – or at least the left side of the screen.

  4.   Ernesto — December 31, 2012 @ 8:18 am    Reply

    > you havn’t shown how to put a control in a grid row in code?

    yes, this part is missing. :(

RSS feed for comments on this post. TrackBack URI

Leave a comment

© 2014 Deborah's Developer MindScape   Provided by WPMU DEV -The WordPress Experts   Hosted by Microsoft MVPs