How do I align text like columns in a treeview? - c#

I have a TreeView where I want to arrange my data nicely.
I format my string like this:
string name = ItemName;
string current = ("Current: " + info.Current.ToString() + " " + identifier);
string maximum = ("Maximum: " + info.Max.ToString() + " " + identifier);
string minimum = ("Minimum: " + info.Min.ToString() + " " + identifier);
string output = string.Format("{0,-20}{1,-30}{2,-30}{3,-30}{4,-30}", name, current, maximum, minimum, average);
dataNode.Text = output;
When I write output to the console it prints it the way I want it, like this (values are off, but that's irrelevant):
Load Current: 9,23 % Maximum: 33,33 % Minimum: 6,06 % Average: 0 %
Temperature Current: 40 °C Maximum: 49 °C Minimum: 38 °C Average: 0 °C
Clock Current: 1200 Mhz Maximum: 2800,09 Mhz Minimum: 1200 Mhz Average: 0 Mhz
etc..
But when I print the exact same strings to my TreeView it shows it like this:
I followed the example on this page but that didn't work for me.
I guess it has something to do with the different nodes I use in my TreeView but I don't know how to properly align my data.

seems like you need to set monospaced font for TreeView.
here is a similar question with example of monospaced font (FontFamily.GenericMonospace):
C# .NET multiline TextBox with same-width characters

This is a perfect situation for .PadRight() or .PadLeft().
string output =
string.Format("{0}{1}{2}{3}{4}",
name.PadRight(20),
current.PadRight(30),
maximum.PadRight(30),
minimum.PadRight(30),
average.PadRight(30));
This code will ensure that the space taken up by each parameter is the same every time.

You can use other controls how alow to create columns like :
There are a number of sample controls to be found around the web:
TreeViewAdv for .Net
TreeView with Columns
ContainerListView and TreeListView

Try just to change font of treeView to use a
non-proportional font like "Courier" , "Consolas"

Related

Peso Symbol in C#

if (num1 == 5)
{
Console.WriteLine("\nThe " + num2 + " kilo/s of {0} " + 28 + " per kilo ", "GRAPES");
Console.WriteLine("The total amount is {0}{1}", num2.ToString("en-PHI"),num2*28);
}
num2.ToString("en-PHI")
I try this one but it doesn't work at all .. it just copy the en-PHI..
Sounds like you want to provide the culture en-PHI... although that isn't a valid culture name apparently. Perhaps you just want phi as the language?
var culture = CultureInfo.GetCultureInfo("phi");
var text = string.Format(culture, "The total amount is {0:c}", num2 * 28);
Console.WriteLine(text);
The c format specifier is "currency".
That's the way of printing the currency symbol known for a specific culture... now that might not do exactly what you want, but it's probably a matter of finding the right culture.
If you really just want to hard-code the peso character (U+20B1) you can do that directly:
Console.WriteLine("The total amount is \u20b1{0}", num2);
Now if that prints a "?" it means the current console encoding or font doesn't support the peso symbol. Running this from the command line will set it to UTF-8:
> chcp 65001
Make sure the font you're using supports the character as well.

How to format a string with fixed width fields

I'm was wondering if there is a way to format a string to format a string, what I mean is, I have a foreach loop that get a information from some files and how many records has each file, as the length of each file is different the format is change.
My example is, I have 3 files:
1.- MyFile1.txt RecordCount: 5
2.- anotherfile.txt RecordCount: 8
3.- MyTestFile.doc RecordCount: 17
As you can see are not formated, I want something like this:
1.- MyFile1.txt RecordCount: 5
2.- anotherfile.txt RecordCount: 8
3.- MyTestFile.doc RecordCount: 17
does not matter the length of the file, RecordCount will be in the same place.
What I have is this:
foreach (RemoteFileInfo file in MySession.EnumerateRemoteFiles(directory.RemoteDirectory, directory.RemoteFiles, EnumerationOptions.None))
{
BodyMessage.Append((index + 1) + ". " + file.Name + " Record Count: " + File.ReadAllLines(Path.Combine(directory.LocalDirectory, file.Name)).Length.ToString() + "\n");
index++;
}
Any idea?
You can try using \t in your strings which will insert a tab or you can try padding each portion so they always take up the same amount space.
For example:
string fileName = file.Name.PadRight(50);
will ensure that the string fileName is at least 50 characters long. I say at least because you could always have a file name that is larger than 50 characters.
foreach (RemoteFileInfo file in MySession.EnumerateRemoteFiles(directory.RemoteDirectory, directory.RemoteFiles, EnumerationOptions.None))
{
int lines= File.ReadAllLines(Path.Combine(directory.LocalDirectory, file.Name)).Length.ToString();
string appending = String.Format("{0,2}.- {1,-18} RecordCount: {3}", file.Name, lines);
BodyMessage.Append(appending);
index++;
}
See MSDN: String.Format Method.
Firstly, use string.Format, rather than concatenation:
int lineCount = File.ReadAllLines(Path.Combine(directory.LocalDirectory, file.Name)).Length.ToString();
string message = string.Format("{0}. {1}\t Record Count: " {2}\n", (index + 1), file.Name, lineCount);
To answer your question, you can align text within a formatted string using the following syntax:
string message = string.Format("{0}. {1,-10}\t Record Count: " {2}\n", (index + 1), file.Name, lineCount);
The additional -10 will ensure that the inserted text is left-padded to 10 characters.
I think you can use PadRight or PadLeft function for this.
string _line = item.FirstName.PadRight(20) + item.Number.PadRight(20) + item.State.PadRight(20) + item.Zip.PadRight(20);
file.WriteLine(_line);

Line up Characters

I have a combobox made up of two numbers; inches and millimetres. At the moment it is looking hideous. I am wondering if some of the gurus here have anyway of lining the character '|' or at least make it nicer?
A bit of background info, the number inches and millimetres are separate strings which I append together like so:
Size(in) + " (In) | " + Size(mm) + " (mm)"
Possibly the cleanest way would be to format every number to have 3 decimal places for at least inches. This still won't be perfect however since the letter font width won't be perfect, to fix that you'd need to use a monospaced font.
To format to 3dp you can use the following
String.Format("{0:f3}", Size(in)) + " (In) | " + Size(mm) + " (mm)"
Since you have some values that are 2 digits before the decimal you can always use PadLeft to align these, but again this doesn't always work well without a monospaced font..
String.Format("{0:f3}", Size(in)).PadLeft(5, ' ') // or (5, '0')
Use String.PadRight(i); and String.PadLeft(i); where i is a nr. of spaces to "fill":
Example:
// Just to simplify a little, create vars:
var inches = Size(in) + " (In) ";
var mm = " + Size(mm) + " (mm)";
var formatted = inches.PadRight(15) + "|" + mm.PadLeft(15);
Example of output using 15 for the padding value (obviously, you can adjust this as needed):
43 inches | 123 cm
445554 inches | 12345 cm

Format decimal value to string with leading spaces

How do I format a decimal value to a string with a single digit after the comma/dot and leading spaces for values less than 100?
For example, a decimal value of 12.3456 should be output as " 12.3" with single leading space. 10.011 would be " 10.0". 123.123 is "123.1"
I'm looking for a solution, that works with standard/custom string formatting, i.e.
decimal value = 12.345456;
Console.Write("{0:magic}", value); // 'magic' would be a fancy pattern.
This pattern {0,5:###.0} should work:
string.Format("{0,5:###.0}", 12.3456) //Output " 12.3"
string.Format("{0,5:###.0}", 10.011) //Output " 10.0"
string.Format("{0,5:###.0}", 123.123) //Output "123.1"
string.Format("{0,5:###.0}", 1.123) //Output " 1.1"
string.Format("{0,5:###.0}", 1234.123)//Output "1234.1"
Another one with string interpolation (C# 6+):
double x = 123.456;
$"{x,15:N4}"// left pad with spaces to 15 total, numeric with fixed 4 decimals
Expression returns: " 123.4560"
value.ToString("N1");
Change the number for more decimal places.
EDIT: Missed the padding bit
value.ToString("N1").PadLeft(1);
Many good answers, but this is what I use the most (c# 6+):
Debug.WriteLine($"{height,6:##0.00}");
//if height is 1.23 => " 1.23"
//if height is 0.23 => " 0.23"
//if height is 123.23 => "123.23"
All above solution will do rounding of decimal, just in case somebody is searching for solution without rounding
decimal dValue = Math.Truncate(1.199999 * 100) / 100;
dValue .ToString("0.00");//output 1.99
Note the "." could be a "," depending on Region settings, when using string.Format.
string.Format("{0,5:###.0}", 0.9) // Output " .9"
string.Format("{0,5:##0.0}", 0.9) // Output " 0.9"
I ended up using this:
string String_SetRPM = $"{Values_SetRPM,5:##0}";
// Prints for example " 0", " 3000", and "24000"
string String_Amps = $"{(Values_Amps * 0.1),5:##0.0}";
// Print for example " 2.3"
Thanks a lot!

Format a string into columns

Is there a cool way to take something like this:
Customer Name - City, State - ID
Bob Whiley - Howesville, TN - 322
Marley Winchester - Old Towne, CA - 5653
and format it to something like this:
Customer Name - City, State - ID
Bob Whiley - Howesville, TN - 322
Marley Winchester - Old Towne, CA - 5653
Using string format commands?
I am not too hung up on what to do if one is very long. For example this would be ok by me:
Customer Name - City, State - ID
Bob Whiley - Howesville, TN - 322
Marley Winchester - Old Towne, CA - 5653
Super Town person - Long Town Name, WA- 45648
To provide some context. I have a drop down box that shows info very similar to this. Right now my code to create the item in the drop down looks like this:
public partial class CustomerDataContract
{
public string DropDownDisplay
{
get
{
return Name + " - " + City + ", " + State + " - " + ID;
}
}
}
I am looking for a way to format this better. Any ideas?
This is what I ended up with:
HttpContext.Current.Server.HtmlDecode(
String.Format("{0,-27} - {1,-15}, {2, 2} - {3,5}",
Name, City, State, ID)
.Replace(" ", " "));
The HtmlDecode changes the to a space that can withstand the space removing formatting of the dropdown list.
You can specify the number of columns occupied by the text as well as alignment using Console.WriteLine or using String.Format:
// Prints "--123 --"
Console.WriteLine("--{0,-10}--", 123);
// Prints "-- 123--"
Console.WriteLine("--{0,10}--", 123);
The number specifies the number of columns you want to use and the sign specifies alignment (- for left alignment, + for right alignment). So, if you know the number of columns available, you could write for example something like this:
public string DropDownDisplay {
get {
return String.Format("{0,-10} - {1,-10}, {2, 10} - {3,5}"),
Name, City, State, ID);
}
}
If you'd like to calculate the number of columns based on the entire list (e.g. the longest name), then you'll need to get that number in advance and pass it as a parameter to your DropDownDisplay - there is no way to do this automatically.
In addition to Tomas's answer I just want to point out that string interpolation can be used in C# 6 or newer.
// with string format
var columnHeaders1 = string.Format($"|{0,-30}|{1,-4}|{2,-15}|{3,-30}|{4,-30}|{5,-30}|{6,-30}", "ColumnA", "ColumnB", "ColumnC", "ColumnD", "ColumnE", "ColumnF", "ColumnG");
// with string interpolation
var columnHeaders2 = $"|{"ColumnA",-30}|{"ColumnB",-4}|{"ColumnC",-15}|{"ColumnD",-30}|{"ColumnE",-30}|{"ColumnF",-30}|{"ColumnG",-30}";
I am unable to add a comment above, but in the accepted answer it was stated:
If you'd like to calculate the number of columns based on the entire list (e.g. the longest name), then you'll need to get that number in advance and pass it as a parameter to your DropDownDisplay - there is no way to do this automatically.
This can in fact be done programmatically at runtime by creating the format string 'on the fly':
string p0 = "first";
string p1 = "separated by alignment value x";
int x = n * 10; // calculate the alignment x as needed
// now use x to give something like: {0,-20}, {1}
string fmt = "{0,-" + x + "},{1}"; // or whatever formatting expression you want
// then use the fmt string
string str = string.Format(fmt, p0, p1)
// with n = 2 this would give us
"first ,separated by alignment value x"

Categories

Resources