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

フォームとリストボックスコントロールの両方でRefresh()とUpdate()を試しましたが、どちらも効果がありません。リストボックスのスクロールバーの問題を探しましたが、この独特の再描画の問題はないようです。

これはどのように見えるべきかです:
ここに画像の説明を入力してください

これが実際に起こっていることです:
ここに画像の説明を入力してください

何か明らかなものが欠けている、あるいはアイテムを間違って変更しているような気がしますが、これについては新鮮です。私は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;
    }
}
4

2 に答える 2

3

問題はアンパサンド文字にあるようです。アイテムを追加すると、正しく測定されているようです。アイテムを更新すると、更新されません。

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

または、追加または変更するすべてのアイテムの値に切り替えて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);
  }
}
于 2012-04-10T19:45:30.780 に答える