2012-04-10 103 views
3

リストボックスの内容を決定する他の多くのコントロールを含むリストボックスコントロールを含むフォームがあります。リストボックスに項目を追加すると、スクロールバーの範囲が正しく設定されますが、リストボックスの項目を更新すると(this.lstResources.Items [index] = myUriを使用)、最後の数文字を切り捨ててスクロールバーの範囲が最大項目幅を超えます。スクロールバーは引き続き動作しますが、このようにリストボックスを更新すると、リスト内の項目の予期せぬ許容できないスクロール範囲が発生します。フォームの両方で、私は(最新の情報に更新を試してみましたリストボックスの水平スクロールバーが正しく更新されない

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

)およびアップデート():次のように私は、このリストボックスで実行変更操作がある

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); 

:ここで私は私のリストボックスを実装しています方法ですリストボックスのコントロールには影響しません。私は、リストボックスのスクロールバーの問題については、すべてを見てきましたが、この独特の再描画の問題はないようです。

これは、それがどのように見えるかです:
enter image description here

これは実際に何が起こっているかである。
enter image description here

私は何かを明らかに不足しているか、おそらく間違ってアイテムを変更してる感じを持っています、私はこのアイデアから新鮮です。私はC#とUIの設計に全く新しいものではありませんが、私はすべての根っこの制御操作も知っているとは言えません。どんな援助も高く評価されるだろう。

EDIT 1:これは問題を再現する必要があるサンプルフォームです。私はこの問題は、アンパサンド文字であるように思わ

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

それを再現することはできません:

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のバージョンがあります。 ListBox項目を変更すると、スクロールバーの範囲が変更されます。 – LarsTech

+0

スクロールバーの範囲を追跡して自分でデバッグできる方法はありますか?おそらく非公開のプロパティですか?私はもっ​​と多くのコードを提供するだろうが、私は残りが適切であるとは思わない。私はそれらを更新するために各リストアイテムをループしていますが、それは関連する外部コードの程度です。 編集:これらの操作がリストボックスと同じオブジェクトで実行されていないことがわかります。 – covertCoder

+0

それとは逆のやり方です。新しいプロジェクトを作成し、最小限のコードで問題を再現します。そのコードを投稿してください。誰も見ることができないコードを見ているので、助けが難しいです。 – LarsTech

答えて

2

...のStringBuilderが更新部とは何かを持っているかもしれないが、それは同様btnAdd_Clickコードでも使用されていることを疑いを持って始めています。アイテムを追加すると、正しく測定されているようです。アイテムを更新すると、アイテムは更新されません。

この醜いハックは、次のように思われます。インデックスを記録し、アイテムを削除し、その記録されたインデックスにアイテムを戻します。

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 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

うわー、これは素晴らしいです!私はこれを介して作業し、それがどのようになっているかを知らせます。私はそれがそうであるように始まるバグである限り、「醜い」コードでうまくいく。 – covertCoder

+0

魅力のように働きます(ResizeListBox()は少なくともあります)、あなたの時間と労力をかけてくれてありがとうLarsTechに感謝します。 – covertCoder

+1

TextFormatFlags.SingleLineを使用する必要がありました。 TextRenderer.MeasureText()内のTextFormatFlags.NoPrefixを使用して機能させます。 – huha

関連する問題