/// <summary>
        /// 
        /// </summary>
        /// <param name="displayCharacter"></param>
        /// <exception cref="ArgumentNullException">
        /// No arguments can be null.
        /// </exception>
        public override FlowDocument Render(DisplayCharacter displayCharacter)
        {
            if (displayCharacter == null)
            {
                throw new ArgumentNullException("displayCharacter");
            }

            FlowDocument result;

            result = new FlowDocument();

            StyleHelper.AddStyles<Block>(result);
            AddImages(result);

            result.Blocks.Add(RenderHeader( displayCharacter.Character, result.Resources));
            result.Blocks.Add(RenderStatistics( displayCharacter.Character, result.Resources));
            result.Blocks.AddRange(RenderPowers(displayCharacter, result.Resources));
            result.Blocks.Add(RenderAbilities( displayCharacter.Character, result.Resources));
            result.Blocks.Add(RenderGear( displayCharacter.Character, result.Resources));

            return result;
        }
 /// <summary>
 /// Render out the <see cref="DisplayCharacter"/> to the given <see cref="FlowDocument"/>.
 /// </summary>
 /// <param name="displayCharacter">
 /// The <see cref="DisplayCharacter"/> to render.
 /// </param>
 /// <exception cref="ArgumentNullException">
 /// No argument can be null.
 /// </exception>
 public abstract FlowDocument Render(DisplayCharacter displayCharacter);
        /// <summary>
        /// Render.
        /// </summary>
        /// <param name="displayCharacter">
        /// The <see cref="DisplayCharacter"/> to render.
        /// </param>
        /// <returns>
        /// A <see cref="FlowDocument"/> containing the character.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// No argument can be null.
        /// </exception>
        public override FlowDocument Render(DisplayCharacter displayCharacter)
        {
            if (displayCharacter == null)
            {
                throw new ArgumentNullException("displayCharacter");
            }

            FlowDocument result;
            Table table;
            TableRowGroup tableRowGroup;

            result = new FlowDocument();
            StyleHelper.AddStyles<TextElement>(result);

            result.Blocks.Add(RenderHeader(displayCharacter.Character, result.Resources));

            table = SetupTable(result.Resources);

            // Table
            tableRowGroup = table.RowGroups.Last();
            table.RowGroups.Add(RenderEncounterPowers(displayCharacter, result.Resources));
            table.RowGroups.Add(RenderHitPoints(displayCharacter, result.Resources));

            result.Blocks.Add(table);

            return result;
        }
        /// <summary>
        /// Render out the section containing hit points and healing surges.
        /// </summary>
        /// <param name="displayCharacter">
        /// The <see cref="DisplayCharacter"/> to display.
        /// </param>
        /// <param name="resourceDictionary">
        /// A <see cref="ResourceDictionary"/> containing styles.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// No argument can be null.
        /// </exception>
        private TableRowGroup RenderHitPoints(DisplayCharacter displayCharacter, ResourceDictionary resourceDictionary)
        {
            if (displayCharacter == null)
            {
                throw new ArgumentNullException("displayCharacter");
            }
            DictionaryHelper.Expect<Style>(resourceDictionary, StyleHelper.TraitHeaderRowStyleName);

            TableRowGroup tableRowGroup;
            TableRow tableRow; // Reused
            TableCell tableCell; // Reused
            Style style;

            style = (Style)resourceDictionary[StyleHelper.TraitHeaderRowStyleName];

            tableRowGroup = new TableRowGroup();
            tableRowGroup.Style = style;
            tableRow = new TableRow();

            // Add the Hit Points title
            tableCell = new TableCell() { ColumnSpan = NameColumnSpan + NumEncounters };
            tableCell.Blocks.Add(new Paragraph(new Run(string.Format("Hit Points: {0}",
                displayCharacter.Character[ScoreType.HitPoints].ToString("CS")))));
            tableRow = new TableRow();
            tableRow.Cells.Add(tableCell);
            tableRowGroup.Rows.Add(tableRow);

            // Add the Hit Points box
            tableCell = new TableCell() { ColumnSpan = NameColumnSpan + NumEncounters };

            Table hitPointsTable;
            TableRowGroup hitPointsTableRowGroup;
            TableRow hitPointsTableRow;
            TableCell hitPointsTableCell;
            Paragraph hitPointParagraph;

            hitPointParagraph = new Paragraph();
            hitPointParagraph.Inlines.Add(new Run(displayCharacter.Character.HitPoints.Total.ToString()));
            for (int i = 0; i < 4; i++)
            {
                hitPointParagraph.Inlines.Add(new LineBreak());
            }

            hitPointsTableCell = new TableCell();
            hitPointsTableCell.Blocks.Add(hitPointParagraph);

            hitPointsTableRow = new TableRow();
            hitPointsTableRow.Cells.Add(hitPointsTableCell);

            hitPointsTableRowGroup = new TableRowGroup();
            hitPointsTableRowGroup.Rows.Add(hitPointsTableRow);

            hitPointsTable = new Table();
            hitPointsTable.BorderBrush = Brushes.Black;
            hitPointsTable.BorderThickness = new Thickness(72 / 96.0); // 1pt
            hitPointsTable.Background = Brushes.White;
            hitPointsTable.Margin = new Thickness(0);
            hitPointsTable.Padding = new Thickness(0);
            hitPointsTable.RowGroups.Add(hitPointsTableRowGroup);

            tableCell.Blocks.Add(hitPointsTable);

            tableRow = new TableRow();
            tableRow.Cells.Add(tableCell);
            tableRowGroup.Rows.Add(tableRow);

            return tableRowGroup;
        }
        /// <summary>
        /// Render out encounter powers.
        /// </summary>
        /// <param name="displayCharacter">
        /// The character to write out the encounter powers for.
        /// </param>
        /// <param name="resourceDictionary">
        /// A <see cref="ResourceDictionary"/> containing styles.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// No argument can be null.
        /// </exception>
        private TableRowGroup RenderEncounterPowers(DisplayCharacter displayCharacter, ResourceDictionary resourceDictionary)
        {
            if (displayCharacter == null)
            {
                throw new ArgumentNullException("displayCharacter");
            }
            DictionaryHelper.Expect<Style>(resourceDictionary, StyleHelper.EncounterHeaderRowStyleName);

            List<Power> powers;
            TableRowGroup tableRowGroup;
            Style style;

            powers = new List<Power>();
            powers.AddRange(displayCharacter.Character.GetUsablePowers().Where(x => x.Frequency == PowerFrequency.Encounter));
            powers.Sort((x, y) => x.Name.CompareTo(y.Name));

            style = (Style)resourceDictionary[StyleHelper.EncounterHeaderRowStyleName];

            tableRowGroup = new TableRowGroup();
            foreach (Power power in powers)
            {
                TableRow tableRow;

                tableRow = new TableRow();
                tableRow.Cells.Add(
                    new TableCell(new Paragraph(new Run(GetPowerHeading(power))) { Style = style }) { ColumnSpan = NameColumnSpan });
                for (int i = 0; i < NumEncounters; i++)
                {
                    tableRow.Cells.Add(new TableCell(RenderBoxes(1, style)) { TextAlignment = TextAlignment.Center });
                }

                tableRowGroup.Rows.Add(tableRow);
            }

            return tableRowGroup;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="displayCharacter"></param>
        /// <param name="resourceDictionary"></param>
        /// <returns></returns>
        private IEnumerable<Block> RenderPowers(DisplayCharacter displayCharacter, ResourceDictionary resourceDictionary)
        {
            List<PowerEntry> powerEntries;
            Item originalMainHand;
            Item originalOffHand;

            powerEntries = new List<PowerEntry>();

            // Add entries to the power list
            if (displayCharacter.ItemPowerDisplays.Count == 0)
            {
                powerEntries.AddRange(ConstructPowers( displayCharacter.Character, x => true, resourceDictionary));
            }
            else
            {
                originalMainHand = displayCharacter.Character.GetHeldItem<Item>(Hand.Main);
                originalOffHand = displayCharacter.Character.GetHeldItem<Item>(Hand.Off);

                try
                {
                    foreach (ItemPowerDisplay itemPowerDisplay in displayCharacter.ItemPowerDisplays)
                    {
                        displayCharacter.Character.SetHeldItem(Hand.Off, null);
                        displayCharacter.Character.SetHeldItem(Hand.Main, itemPowerDisplay.MainHand);
                        displayCharacter.Character.SetHeldItem(Hand.Off, itemPowerDisplay.OffHand);
                        displayCharacter.Character.Update();
                        powerEntries.AddRange(ConstructPowers(displayCharacter.Character,
                            itemPowerDisplay.Predicate, resourceDictionary));
                    }
                }
                finally
                {
                    displayCharacter.Character.SetHeldItem(Hand.Off, null);
                    displayCharacter.Character.SetHeldItem(Hand.Main, originalMainHand);
                    displayCharacter.Character.SetHeldItem(Hand.Off, originalOffHand);
                    displayCharacter.Character.Update();
                }
            }

            powerEntries.AddRange(ConstructTraits(displayCharacter.Character, resourceDictionary));

            return RenderPowerEntries(powerEntries, resourceDictionary);
        }