2012-04-10 77 views
3

我有一個窗體,其中包含一個列表框控件與許多其他控件確定列表框內容。將項目添加到列表框正確設置滾動條的範圍,但更新列表框上的項目(通過this.lstResources.Items [index] = myUri)會導致滾動條的範圍減少到最大項目的寬度,從而截斷最後幾個字符。滾動條仍然有效,但以這種方式更新列表框會導致意外且無法接受的列表中項目的滾動範圍。這裏是我如何實現我的列表框:列表框水平滾動條沒有正確更新

public System.Windows.Forms.ListBox lstResources; 
this.lstResources = new System.Windows.Forms.ListBox(); 

this.lstResources.FormattingEnabled = true; 
this.lstResources.HorizontalScrollbar = true; 
this.lstResources.Location = new System.Drawing.Point(331, 122); 
this.lstResources.Name = "lstResources"; 
this.lstResources.Size = new System.Drawing.Size(307, 316); 
this.lstResources.TabIndex = 8; 
this.lstResources.Click += new System.EventHandler(this.ResourcesPage.LstResources_Click); 

,我在這個列表框進行的改變操作如下:

this.parentClassReference.lstResources.Items.Add(myUri); 
this.parentClassReference.lstResources.Items[index] = myUri; 
this.parentClassReference.lstResources.Items.RemoveAt(index); 

我已經從表格上試圖刷新()和Update()和列表框控件,但都沒有任何作用。我查看了所有的列表框滾動條問題,但沒有人似乎有這個奇怪的重繪問題。

這是它應該是什麼樣子:
enter image description here

這是實況:
enter image description here

我有一種感覺,我缺少明顯的東西或者是改變不正確的項目,但是我對這個想法很新鮮。我並不是全新的C#和UI設計,但我不能說我知道所有的基本控制操作。任何援助將不勝感激。

編輯1:這是一個應該重現問題的示例表單。我開始有一個懷疑,StringBuilder的可能有一些做的更新的一部分,但它也可用於在btnAdd_Click代碼以及...

public partial class SampleListBoxForm : Form 
{ 
    public Dictionary<string, string> CurrentUriQuery { get; set; } 

    public SampleListBoxForm() 
    { 
     this.CurrentUriQuery = new Dictionary<string, string>(); 
     this.InitializeComponent(); 
    } 

    private void btnAdd_Click(object sender, EventArgs e) 
    { 
     this.UpdateParams("sampleApp"); 
     this.listBox1.Items.Add(this.GenerateURI()); 
     this.listBox1.Refresh(); 
    } 

    private void btnUpdate_Click(object sender, EventArgs e) 
    { 
     int index = 0; 
     this.UpdateParams("sampleApp2"); 
     for (; index < this.listBox1.Items.Count; index++) 
     { 
      this.listBox1.Items[index] = this.GenerateURI(); 
     } 
    } 

    private void UpdateParams(string filename) 
    { 
     this.CurrentUriQuery = new Dictionary<string, string>(); 
     this.CurrentUriQuery["filename"] = filename; 
     this.CurrentUriQuery["url"] = @"C:\Users\me\Desktop\" + filename; 
     this.CurrentUriQuery["type"] = "dynamicType"; 
     this.CurrentUriQuery["p1"] = "foo"; 
     this.CurrentUriQuery["p2"] = "bar"; 
     this.CurrentUriQuery["p3"] = "stuff"; 
     this.CurrentUriQuery["p4"] = "test"; 
    } 

    private string GenerateURI() 
    { 
     StringBuilder currentUri = new StringBuilder(); 
     bool firstParam = true; 
     currentUri.Append(this.CurrentUriQuery["filename"]); 
     foreach (KeyValuePair<string, string> pair in this.CurrentUriQuery) 
     { 
      if (pair.Key != "url" && pair.Key != "filename" && pair.Value != string.Empty && pair.Value != "0") 
      { 
       if (firstParam) 
       { 
        currentUri.Append("?"); 
        firstParam = false; 
       } 
       else 
       { 
        currentUri.Append("&"); 
       } 

       currentUri.Append(pair.Key); 
       currentUri.Append("="); 
       currentUri.Append(pair.Value.Replace(" ", "")); 
      } 
     } 

     return currentUri.ToString(); 
    } 

    public string[] ExtractPathAndQueryFromUriString(string uriString) 
    { 
     string[] pathAndQuery = new string[2]; 
     if (uriString.Contains('?')) 
     { 
      pathAndQuery[0] = uriString.Split('?')[0]; 
      pathAndQuery[1] = uriString.Split('?')[1]; 
     } 
     else if (uriString.Contains("%3F")) 
     { 
      string[] stringSeparator = new string[] { "%3F" }; 
      pathAndQuery[0] = uriString.Split(stringSeparator, StringSplitOptions.None)[0]; 
      pathAndQuery[1] = uriString.Split(stringSeparator, StringSplitOptions.None)[1]; 
     } 
     else 
     { 
      pathAndQuery[0] = uriString; 
      pathAndQuery[1] = string.Empty; 
     } 

     return pathAndQuery; 
    } 
} 
+0

不能複製。更改ListBox項目會更改滾動條範圍。 – LarsTech 2012-04-10 17:01:01

+0

有沒有辦法跟蹤滾動條的範圍,以便我可以自己調試?非公有財產也許?我會提供更多的代碼,但我認爲其餘部分不相關。我遍歷每個列表項來更新它們,但這是關於相關外部代碼的範圍。 編輯:這可能有助於知道這些操作不在與列表框相同的對象中執行,這就是爲什麼它是公開的。 – covertCoder 2012-04-10 17:23:54

+0

反過來做。用最少量的代碼創建一個新項目並重現問題。發佈該代碼。您正在查看其他人無法看到的代碼,這很難提供幫助。 – LarsTech 2012-04-10 17:28:52

回答

2

的問題似乎是通過符號。當您添加該項目時,它似乎正確測量。當您更新該項目時,它不會。

這個醜陋的黑客似乎是:記錄索引,刪除項目,插入項目回記錄索引。

或切換到DrawMode = OwnerDrawFixed並計算您添加或更改的每個項目的HorizontalExtent值。

private void ResizeListBox() { 
    int maxWidth = 0; 

    for (int i = 0; i < listBox1.Items.Count; i++) { 
    int testWidth = TextRenderer.MeasureText(listBox1.Items[i].ToString(), 
              listBox1.Font, listBox1.ClientSize, 
              TextFormatFlags.NoPrefix).Width; 
    if (testWidth > maxWidth) 
     maxWidth = testWidth; 
    } 

    listBox1.HorizontalExtent = maxWidth; 
} 

不幸的是,你必須把它的每一個變化:

private void btnAdd_Click(object sender, EventArgs e) { 
    this.UpdateParams("sampleApp"); 
    this.listBox1.Items.Add(this.GenerateURI()); 
    ResizeListBox(); 
} 

private void btnUpdate_Click(object sender, EventArgs e) { 
    this.UpdateParams("sampleApp"); 
    for (int index = 0; index < this.listBox1.Items.Count; index++) { 
    this.listBox1.Items[index] = this.GenerateURI(); 
    } 
    ResizeListBox(); 
} 

這裏是一個快速和骯髒的DRAWITEM版本:

private void listBox1_DrawItem(object sender, DrawItemEventArgs e) { 
    e.DrawBackground(); 
    if (e.Index > -1) { 
    Color textColor = SystemColors.WindowText; 
    if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) { 
     textColor = SystemColors.HighlightText; 
    } 
    TextRenderer.DrawText(e.Graphics, listBox1.Items[e.Index].ToString(), 
          listBox1.Font, e.Bounds, 
          textColor, Color.Empty, TextFormatFlags.NoPrefix); 
    } 
} 
+0

哇,這太棒了!我會通過這個工作並讓你知道它是如何發展的。只要它是C#的錯誤,我就可以用'醜陋'的代碼開始,它看起來就是這樣。 – covertCoder 2012-04-10 19:50:44

+0

工程就像一個魅力(ResizeListBox()至少),非常感謝您的時間和精力LarsTech。 – covertCoder 2012-04-10 20:17:04

+1

我需要使用TextFormatFlags.SingleLine | TextRenderer.MeasureText()中的TextFormatFlags.NoPrefix使其工作。 – huha 2014-03-03 13:56:11