How to Work with Lists in .NET

How to Work with Lists in .NET

How to Work with Lists in .NET

Numbered and bulleted lists in a Word document are built from three cooperating objects: List, the reusable numbering definition; ListFormat, which tells a specific paragraph which list and level it belongs to; and ListLevel, which holds the actual formatting for one level. This guide shows how to apply a list to a paragraph, keep separate lists from sharing a counter, move paragraphs between levels, and customize numbering and bullet formatting with Aspose.Words FOSS for .NET.


Step-by-Step Guide

Step 1: Apply a List to a Paragraph

Use ListFormat.ApplyBulletDefault() or ApplyNumberDefault() on a paragraph’s formatting to apply Word’s default bullet or numbered list in one call — this is the quickest way to apply a standard list. For a specific predefined format instead of the default, call Document.Lists (a ListCollection) .Add(listTemplate) with a ListTemplate value such as BulletDisk, BulletSquare, NumberArabicDot, or NumberUppercaseRomanDot to create a List from one of Word’s built-in formats, or AddSingleLevelList(listTemplate) for a single-level variant. Once a paragraph has list formatting, ListFormat.IsListItem reports true, and ListFormat.List/ListLevelNumber identify which list and level it uses.


Step 2: Give a New Group of Paragraphs Independent Numbering

Paragraphs whose ListFormat.List points at the same shared List object continue the same counter. When a new group of paragraphs needs numbering that restarts from 1 independently, call ListCollection.AddCopy(srcList) to duplicate an existing list definition, then apply the copy to the new paragraphs instead of reusing the original. ListCollection.GetListByListId(listId) retrieves a specific list by its ListId when you need to look one up rather than create one, and Count reports how many lists the document currently has.


Step 3: Move a Paragraph Between List Levels

Use ListFormat.ListIndent() to move a paragraph one level deeper into its list, and ListOutdent() to move it one level shallower — the same operations Word performs for Tab and Shift+Tab at the start of a list paragraph. Prefer these methods over setting ListLevelNumber directly, since they keep the paragraph’s list formatting internally consistent. Call RemoveNumbers() to strip list formatting from a paragraph entirely.


Step 4: Customize a List Level’s Numbering Format

Reach a specific level through List.ListLevels (a ListLevelCollection), then set ListLevel.NumberStyle (a NumberStyle value such as Arabic, UppercaseRoman, LowercaseLetter, or Bullet) and NumberFormat — the format string combining the number with literal text such as a period or parenthesis — together, since a mismatched pair produces unexpected rendering. StartAt sets the level’s starting number, and RestartAfterLevel controls which higher level’s increment restarts this level’s counter — set it explicitly on nested lists rather than relying on default restart behavior. Alignment (Left, Center, Right) and TrailingCharacter (Tab, Space, Nothing) control label position and the separator between the label and the paragraph text, alongside TabPosition, NumberPosition, and TextPosition for precise layout. IsLegal forces legal-style numbering (always Arabic) regardless of NumberStyle.


Step 5: Add a Picture Bullet to a List Level

Call ListLevel.CreatePictureBullet() on the target level to create a picture-bullet definition, then supply the bullet’s ImageData before removing any existing text-bullet formatting on the same level. Call DeletePictureBullet() to remove a picture bullet and revert to text-based bullet formatting.


Step 6: Inspect a List Item’s Rendered Label

ListLabel describes the label actually rendered for one list item instance, reached from the item’s paragraph formatting. LabelString is the literal text Word displays — such as “3.” or “•” — LabelValue is the underlying numeric value, and Font is the label’s own formatting, independent of the paragraph text’s formatting. For computing a label’s value at an arbitrary position in the sequence without rendering the whole list, call ListLevel.GetEffectiveValue(index, numberStyle, customNumberStyleFormat).


Common Issues and Fixes

Two paragraphs that should number independently continue the same sequence. Both paragraphs’ ListFormat.List refers to the same shared List object. Give the second group its own list via ListCollection.AddCopy(srcList) instead of reusing the same List.

A custom numbering format string doesn’t render as expected. ListLevel.NumberFormat doesn’t match the pattern expected for the level’s NumberStyle. Verify NumberFormat and NumberStyle are set consistently for the level being edited.

List indentation looks wrong after changing levels programmatically. ListLevelNumber was set directly without updating related position properties. Use ListFormat.ListIndent()/ListOutdent() instead of setting ListLevelNumber directly.

A picture bullet doesn’t appear on a level. No picture bullet was created for that level, or default text-bullet formatting is still active. Call ListLevel.CreatePictureBullet() and supply the image data before removing text bullet formatting.

A style-linked list doesn’t respond to direct formatting changes. Check List.IsListStyleReference — a style-referencing list’s formatting is controlled by its linked Style (via List.Style), not by editing the list directly. Compare against IsListStyleDefinition to distinguish a list that defines its own formatting.


Frequently Asked Questions

What’s the difference between List and ListFormat?

List is the reusable numbering or bullet definition shared across paragraphs. ListFormat is per-paragraph — it points at which List a specific paragraph uses and at which level, via ListFormat.List and ListLevelNumber.

How do I check whether a paragraph is already part of a list?

Read ListFormat.IsListItem on the paragraph’s formatting. If true, ListFormat.List and ListLevelNumber identify which list and level it belongs to.

How do I make a new list start numbering from 1 independently of an existing list?

Use ListCollection.AddCopy(srcList) to create an independent copy of the list definition, then apply the copy to the new paragraphs rather than reusing the original List, which would continue the same counter.

How do I create a bulleted or numbered list from scratch?

Use ListFormat.ApplyBulletDefault() or ApplyNumberDefault() for Word’s default formatting, or ListCollection.Add(listTemplate) with a ListTemplate value to start from a predefined format and customize the resulting List.ListLevels from there.

How do I get a number format like “1)” instead of “1.”?

Set ListLevel.NumberFormat on the relevant level to the desired format string, alongside NumberStyle for the numeral style itself.


See Also