String.Format won't create correct spacing, exhausted every method

this may seem like a trivial question, but I swear I have exhausted every method I can find. I'm trying to output the contents of a dictionary to a textbox. This is written in C#. Idk how relevant it is, but I'm outputing to a WPF textbox. I've tried the following methods:

Dictionary<string, int> nGramDictionary = StatisticalBreakDown.getNGramFrequency(filePath, 3);
MasterStatsTextBlock.Text += "~N-Gram Frequency~" + "\r\n";
foreach (var kvp in nGramDictionary)
{
    MasterStatsTextBlock.Text += string.Format("{0,-40}{1}{2}", kvp.Key, kvp.Value, Environment.NewLine);
}
MasterStatsTextBlock.Text += "\r\n";

and

Dictionary<string, int> nGramDictionary = StatisticalBreakDown.getNGramFrequency(filePath, 3);
MasterStatsTextBlock.Text += "~N-Gram Frequency~" + "\r\n";
foreach (var kvp in nGramDictionary)
{
    MasterStatsTextBlock.Text += string.Format("{0}{1}{2}", kvp.Key.PadRight(-40), kvp.Value, Environment.NewLine);
}
MasterStatsTextBlock.Text += "\r\n";

and

Dictionary<string, int> nGramDictionary = StatisticalBreakDown.getNGramFrequency(filePath, 3);
MasterStatsTextBlock.Text += "~N-Gram Frequency~" + "\r\n";
foreach (var kvp in nGramDictionary)
{
    MasterStatsTextBlock.Text += string.Format("{0}\t\t\t{1}{2}", kvp.Key, kvp.Value, Environment.NewLine);
}
MasterStatsTextBlock.Text += "\r\n";

But neither work. Everyone swears these will work, but they do not. Here's what my output looks like with all three of these:

~N-Gram Frequency~
talan kirk book                        1
kirk book of                         1
book of mormon                        1
of mormon am                          1
mormon am tt                            1
am tt extraction                        1
tt extraction nephi                     1
extraction nephi nephi                1
nephi nephi the                       1
nephi the lord                       1
the lord speaks                        1
lord speaks to                        1
speaks to his                         1
to his children                       1
his children the                       1
children the savior                   1
the savior teaches                     1
savior teaches plainly                1
teaches plainly because                1

Please help. I'm seriously at a loss here as to why these wont work.

Jon Skeet
people
quotationmark

I suspect the problem is that you're using a TextBox, and my guess is that you haven't set the text to a monospace font... but you're trying to use string formatting to position the values accurately.

To investigate string formatting, I'd recommend using a console app instead. For example, the following demo shows string formatting working correctly. Both the key and the value have a maximum length, with the key being left-justified and the value being right-justified:

using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        var data = new Dictionary<string, int>
        {
            { "first", 10 },
            { "second", 1 },
            { "third", 100000 }
        };

        foreach (var entry in data)
        {
            Console.WriteLine("{0,-20}{1,8}", entry.Key, entry.Value);
        }
    }
}

Try that in your WPF UI and you'll probably see the same brokenness - unless you set the font to a monospace font.

However, a monospace font may well look ugly... in which case you may well not want to use a TextBox for this at all. There are other, more advanced text-based controls you could use - or you could use a control which is more geared towards displaying lists/grids of data.

people

See more on this question at Stackoverflow