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
- Download the zip file with the source code, and unzip in a directory.
- Open the OrderedList.sln file in Visual Studio.
- You'll find that the sources are organized in a solution, with these elements:
- Project OrderedList is the actual library.
- Project Test has a series of ordered lists that put the library through its paces. Look here for working examples of the various options.
- The Example projects have the sample code shown in this article.
- 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
- Build the solution.
- Right click tool bar and choose "Add Tab".
- Enter a name for the new tab, such as "Ordered List".
- Right Click the new tab "Ordered List" and choose "choose items". This opens the "Choose Toolbox Items" window.
- Click the Silverlight Tab.
- Click the Browse button and find the OrderedList.dll file you just created.
- Double click OrderedList.dll.
- 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:
- In your project, add a reference to the OrderedList.dll file you generated during Installation.
-
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="☺">
.....
</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:
- In Visual Studio, right click on the image file and choose Properties;
- 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