[C#] Windows Form 的 ListBox 排版對齊問題

最近做簡易的訂單系統,將訂單輸出到 ListBox ,而 ListBox 的每一筆 record 叫作 Item 用字串賦值,如果每一筆 record 都只有一個簡單的值那還 OK,如果很多欄位要串成一個字串給 ListBox.Items.Add(),結果只能說亂到不行,例如下面是每筆訂單有飲料品項名、每杯單價、糖冰狀況:

單純輸出

foreach(Order ord in OrderList)
{
  string item = $"{ord.Name},{ord.Price},{ord.SugarIce}";
  listBox1.Items.Add(item);
}

以上大概是像這樣單純的輸出,只是串接起會很醜無可厚非,那如果加上字串格式化呢?其實結果改善不了多少…

加上長度的字串格式化

foreach(Order ord in OrderList)
{
  string item = $"{ord.Name,6},{ord.Price,4},{ord.SugarIce,-8}";
  Console.WriteLine(item);
  listBox1.Items.Add(item);
}

程式碼順便輸出到 console 一看,一樣是亂七八糟,這是發生了什麼事?原因大概在中文字 string.Length 是照字數算的,例如 "紅茶" 的.Length = 2,如果格式化排 6 個字,靠右對齊,就會在左邊補上 4 個空白字元,而 "起士鮮奶茶" 的.Length = 5,左邊補上 1 個空白字元,看起來很美好,但是為什麼 console 還是很亂?因為一個中文字會佔用 2 個英數字元的位置,造成右邊根本無法對齊,以"紅茶"與"起士鮮奶茶"為例,紅茶兩個中文字其實佔用 4 個英數字元,左邊如果再補上 4 個空白字元,格式化後會佔用 8 個英數字元,而起士鮮奶茶五個中文字其實佔用 10 個英數字元,左邊再 1 個空白字元,格式化共佔用 11 個字元,一個是 8 ,一個是 11 ,當然不齊了。

玩過 BBS 和 DOS 倚天系統的人應該對中文字會佔用 2 個英數字元的這件事很習慣了,所以本來我也以為 "紅茶" 的.Length = 4,而 "起士鮮奶茶" .Length = 10,但其實不然,也就造成上面的問題了。

英數字排版就順利嗎?

如果中文字有這個問題,那麼英文字輸出到 ListBox 就漂亮嗎?其實沒有,下面是全英數字的資料:

foreach(Order ord in OrderList)
{
  string item = $"{ord.Name,18},{ord.Price,3},{ord.SugarIce,17}";
  Console.WriteLine(item);
  listBox1.Items.Add(item);
}

會發現 console 確實有照字串格式化漂亮的對齊了,但是 ListBox 結果慘不忍睹,這可能是 ListBox 先天的問題了吧,其實連 StackOverflow 也有歐美語系的人有這個問題,得到的回答是換使用 ListView …

使用 \t 縮排

如果 ListBox 的各 item 中同一欄的長度差不多,用 \t 字元來縮排是一個辦法,但有其風險,如果剛好超過去再加上 \t ,就會整個往右推去,就亂了:

foreach(Order ord in OrderList)
{
  string item = $"{ord.Name}\t{ord.Price}\t{ord.SugarIce}";
  listBox1.Items.Add(item);
}

所以如果用 ListBox 其中每個 item 是由多個欄位串接成字串的話,還是砍掉重練,改用 ListView 吧……

留言