Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Numbered And Bulleted Lists for Silverlight

0.00/5 (No votes)
8 Jun 2008 1  
Counterpart of HTML's ol and ul tags for Silverlight

Introduction

Silverlight 2 is a great idea, but there are some gaping holes. One of the things I missed was support for ordered and unordered lists - a counterpart for the HTML <ol> and <ul> tags. This library fills that gap.

  • Supports decimal numbers, roman numbers and letters.
  • Wide variety of built in bullets.
  • Lets you use an image as a bullet.
  • Add fixed text to each item number - so you can turn "1" into "Step 1:".
  • Precise control over indentation and space between number and text.
  • Customize color, size, etc.
  • Have a start number other then 1. Or an increment other then 1.
  • Include an item number in each element of a ListBox via its Datatemplate.

Requirements


Installation

  1. Download the zip file with the source code, and unzip in a directory.
  2. Open the OrderedList.sln file in Visual Studio.
  3. You'll find that the sources are organized in a solution, with these elements:
    1. Project OrderedList is the actual library.
    2. Project Test has a series of ordered lists that put the library through its paces. Look here for working examples of the various options.
    3. The Example projects have the sample code shown in this article.
  4. Compile the solution. This will produce a OrderedList.dll file in the OrderedList\ClientBin directory. You'll need that file to use the library in your own projects.

Add OrderedList elements to the toolbox

  1. Build the solution.
  2. Right click tool bar and choose "Add Tab".
  3. Enter a name for the new tab, such as "Ordered List".
  4. Right Click the new tab "Ordered List" and choose "choose items". This opens the "Choose Toolbox Items" window.
  5. Click the Silverlight Tab.
  6. Click the Browse button and find the OrderedList.dll file you just created.
  7. Double click OrderedList.dll.
  8. Click OK to add the controls to the toolbox.

The new controls are only visible when you have a .xaml file open. You won't see them while looking at an .aspx file.

Quick Start

Add references to the library

When you drag an OrderedList element from the toolbox to your page, the editor automatically adds the required namespace/assembly declaration to your page and adds a reference to OrderedList.dll to your project.

However, if you simply type in the XAML, or copy and paste, be sure to to go through these steps to add these things yourself:

  1. In your project, add a reference to the OrderedList.dll file you generated during Installation.

  2. Add a namespace declaration to the UserControl defintion at the top of the .xaml file, like this:

    <UserControl 
        xmlns:my="clr-namespace:OrderedList;assembly=OrderedList"  
        ......
    >
    

Simple list

To add an ordered list on your page, simply add something like the following to the XAML:

<my:OrderedList>
    <StackPanel>
        <my:ListItem>
            <TextBlock>First text item</TextBlock>
        </my:ListItem>

        <my:ListItem>
            <TextBlock>Second text item</TextBlock>
        </my:ListItem>

        <my:ListItem>
            <TextBlock>Third text item</TextBlock>
        </my:ListItem>
    </StackPanel>
</my:OrderedList>

The OrderedList element sets up the list, just as the <ol> and <ul> tags do in HTML. The ListItem element creates a single list item, just like <li> in HTML.

OrderedList is derived from ContentControl, so it can hold only one element. As a result, you need to place the ListItem elements in a StackPanel or a Grid.

Multiple elements per item

ListItem too is derived from ContentControl, so if you have multiple elements within a list item, you need to place them within a StackPanel or Grid as well. Like so:

<my:ListItem>
    <StackPanel>
        <TextBlock>First text item, first text block</TextBlock>
        <TextBlock>First text item, second text block</TextBlock>
        <TextBlock>First text item, third text block</TextBlock>
    </StackPanel>
</my:ListItem>

Nested Lists

Finally, you can place any elements within a ListItem, including more OrderedList elements - to create nested lists:

<my:ListItem>
    <StackPanel>
        <TextBlock>First text item</TextBlock>
        <my:OrderedList>
            <StackPanel>
                <my:ListItem>
                    <TextBlock>First nested text item</TextBlock>
                </my:ListItem>
                <my:ListItem>
                    <TextBlock>Second nested text item</TextBlock>
                </my:ListItem>
                <my:ListItem>
                    <TextBlock>Third nested text item</TextBlock>
                </my:ListItem>
            </StackPanel>
        </my:OrderedList>
    </StackPanel>
</my:ListItem>

Putting it all together

Below is a page with the completed example. You'll find it in the sources you downloaded, in project Example1.
<UserControl x:Class="Example1.Page"
    xmlns:my="clr-namespace:OrderedList;assembly=OrderedList"  
    xmlns="http://schemas.microsoft.com/client/2007" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">

        <my:OrderedList>
            <StackPanel>
                <my:ListItem>
                    <StackPanel>
                        <TextBlock>First text item</TextBlock>
                        <my:OrderedList>
                            <StackPanel>
                                <my:ListItem>
                                    <TextBlock>First nested text item</TextBlock>
                                </my:ListItem>
                                <my:ListItem>
                                    <TextBlock>Second nested text item</TextBlock>
                                </my:ListItem>
                                <my:ListItem>
                                    <TextBlock>Third nested text item</TextBlock>
                                </my:ListItem>
                            </StackPanel>
                        </my:OrderedList>
                    </StackPanel>
                </my:ListItem>

                <my:ListItem>
                    <StackPanel>
                        <TextBlock>Second text item, first text block</TextBlock>
                        <TextBlock>Second text item, second text block</TextBlock>
                        <TextBlock>Second text item, third text block</TextBlock>
                    </StackPanel>
                </my:ListItem>

                <my:ListItem>
                    <TextBlock>Third text item</TextBlock>
                </my:ListItem>
            </StackPanel>
        </my:OrderedList>

    </Grid>
</UserControl>

Datatemplate

You can use a OrderedList to number the items of a ItemsControl, such as a ListBox, like so:

<my:OrderedList>
    <ListBox x:Name="MyBooks" ItemsSource="{Binding Mode=OneWay}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal" >
                    
                    <my:ListNumber/>

                    <TextBlock Text="{Binding Title}" Width="150" Margin="0,0,5,0" />
                    <TextBlock Text="{Binding ISBN}" Width="120" Margin="0,0,5,0"  />
                    <TextBlock Text="{Binding PublishDate}" Width="200" Margin="0,0,5,0" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</my:OrderedList>

Note that:

  • The ListBox sits within the OrderedList.

  • You'll probably be using a DataTemplate to define which bits of data are shown where and how. In that DataTemplate, include a ListNumber at the point where you want to show the item number.

The difference between a ListNumber and a ListItem is that a ListNumber represents just the number itself, while a ListItem takes care of indenting the elements that come after the number. Have a look at the generic.xaml file in the OrderedList project, and you'll see that ListItem actually uses ListNumber to show the actual number.

The project Example2 in the solution you downloaded has a working example of all this.


Number Types

In addition to decimal numbers you can use upper- and lowercase letters and upper- and lowercase roman numerals. You specify the number type via the NumberType property of OrderedList.

For example, to use lowercase roman numerals, you'd write:

<my:OrderedList NumberType="LowerRoman">
.....
</my:OrderedList>

To generate... Use NumberType...
1, 2, 3, 4, ... Decimal (default)
i, ii, iii, iv, ... LowerRoman
I, II, III, IV, ... UpperRoman
a, b, c, d, ... LowerAlpha
A, B, C, D, ... UpperAlpha


Bullets

To make it easy to have bullets instead of numbers, the NumberType property also lets you specify a bullet type. That gives you the counterpart of the HTML <ul> tag.

For example, to use a black square as your bullet, you'd write:

<my:OrderedList NumberType="Square">
.....
</my:OrderedList>

To generate... Use NumberType...
Disc
BigDisc
Circle
BigCircle
Diamond
Lozenge
Square
BigSquare
Pointer

More bullets

If the bullet you want isn't listed above, you can use any Unicode character you want by using the NumberFormat property.

For example, to use a smiley as your bullet, you'd write:

<my:OrderedList NumberFormat="&#9786;">
.....
</my:OrderedList>

You'll find lots of interesting characters in the Unicode Geometric Shapes Block and the Miscellaneous Symbols Block.

Using an image as a bullet

Say you have an image greentick.png in a directory images in your Silverlight Application, with a height of 20 pixels and a width of 20 pixels.

Here is how you would use that image as your bullet:

<my:OrderedList 
         NumberType="Image"
         ImageHeight="20"
         ImageWidth="20"
         ImageSource="images/greentick.png">
.....
</my:OrderedList>

Note that you need to set NumberType to Image.

For this to work, your image needs to be present in the proper directory while the page with your Silverlight is being displayed. To ensure this happens:

  1. In Visual Studio, right click on the image file and choose Properties;
  2. Set "Copy to Output Directory" to "Copy Always".

Also, Silverlight doesn't seem to support .gif files, so you can only use .jpg and .png files.

The Example3 project has working examples of all the bullets.

Suppressing the bullet

If for some reason you don't want a bullet (or number) at all, you'd write:

<my:OrderedList NumberType="None">
.....
</my:OrderedList>

This however also suppresses the indent. If you do want the indent (but no bullet or number), just use an empty string as your bullet:

<my:OrderedList NumberFormat="">
.....
</my:OrderedList>

Parent Numbers

With nested lists, sometimes there is a need to show the numbers of the "parent" items in the "child" items, like this:

To achieve this effect, use the ShowParentNumbers property on the nested list, like this:

<my:OrderedList ShowParentNumbers="True">
.....
</my:OrderedList>

A working example is in the Example4 project. You can have as many nesting levels as you want.


Start and Increment

When using numbers, you don't have to start at 1 and increment by 1.

If you wanted to start at 10 and increment by 5, simply write:

<my:OrderedList Start="10"  Increment="5">
.....
</my:OrderedList>

Adding Fixed Text

Suppose you want to embellish the item numbers with some text, like this:

1) .....
2) .....
3) .....

or even this:

Step 1: .....
Step 2: .....
Step 3: .....

This is easy to achieve with the NumberFormat property:

<my:OrderedList NumberFormat="{}Step {0}:">
.....
</my:OrderedList>

{0} is the placeholder for the actual number or bullet.

{} at the start tells XAML that the {0} should be taken literally, rather then as a Markup Extension.

If you want just fixed text (without a number), leave out both the {0} and the {}.


Spacing and Aligning

The position of the number or bullet, and the indentation of the text, are determined by these properties:

NumberIndent Space in front of the number or bullet
NumberWidth Space for the number or bullet
NumberTextAlignment Alignment (left or right) of the number or bullet within the given space
NumberPostdent Space between the number or bullet and the text

If you don't set any of these properties, you get a default NumberWidth that's big enough for a few digits, a "right" NumberTextAlignment and a small NumberPostdent so the text doesn't hug the number. In most cases, this is what you want.

Sometimes you'll want to set the width yourself, for example to make it big enough for fixed text:

<my:OrderedList 
    NumberIndent="10" 
    NumberWidth="40" 
    NumberPostdent="5" 
    NumberTextAlignment="Left" 
    NumberFormat="{}Step {0}:">
.....
</my:OrderedList>

Example5 has a working example of this.

Spacing for image bullets

Things are slightly different when using image bullets. Here, the property ImageWidth is used instead of NumberWidth, and NumberTextAlignment is ignored:

NumberIndent Space in front of the image bullet
ImageWidth Width of the image bullet
NumberPostdent Space between the image bullet and the text

Number Appearance

How about red bullets? Or really big underlined numbers?

If you have a look at the style for ListNumber towards the end of the generic.xaml file in the OrderedList project, you'll see that the number or bullet sits in a TextBlock element. You can set the most important properties of the TextBlocks holding the numbers or bullets via properties of the OrderedList element. The property names are the same as those for the corresponding TextBlock properties, except they have "Number" prepended. So you can write something like this:

<my:OrderedList NumberForeground="Red" NumberFontFamily="Arial" NumberFontSize="24">
.....
</my:OrderedList>

You can use these properties:

NumberFontFamily Font family of the number, such as "Arial" or "Times New Roman" (full list).
NumberFontStyle "Normal" or "Italic"
NumberFontWeight Set to "Bold" for heavy numbers (more options)
NumberFontSize Font size in pixels
NumberForeground Color of your number or bullet (color list)
NumberTextDecorations Set to "Underline" for underlined text

The Test project within the solution shows the use of some of these properties.


History

9 June 2008: First release, for Silverlight 2 Beta 1
11 June 2008: Converted to Silverlight 2 Beta 2


License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here