2012-04-10 5 views
3

Ich habe ein Formular, das ein Listbox-Steuerelement mit vielen anderen Steuerelementen enthält, die den Listbox-Inhalt bestimmen. Durch das Hinzufügen von Elementen zur Listbox wird der Bereich der Bildlaufleiste korrekt festgelegt, aber das Aktualisieren von Elementen in der Listbox (über this.lstResources.Items [index] = myUri) bewirkt, dass der Bereich der Bildlaufleiste nach der größten Elementbreite abnimmt und die letzten Zeichen abgeschnitten werden. Die Bildlaufleiste funktioniert weiterhin, aber das Aktualisieren des Listenfelds auf diese Weise verursacht einen unerwarteten und inakzeptablen Bildlaufbereich für die Elemente in der Liste. Hier ist, wie ich meine listbox bin der Umsetzung:Listbox horizontale Bildlaufleiste nicht ordnungsgemäß aktualisiert

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

die Änderungsoperationen, die ich auf diesem Listenfeld durchführen, sind wie folgt:

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

Ich habe versucht Refresh() und Update() sowohl auf dem Formular und die Listbox-Kontrolle, aber keine Wirkung. Ich habe überall nach Listbox-Scrollbar-Problemen gesucht, aber keines scheint dieses spezielle Problem mit dem erneuten Zeichnen zu haben.

Dies ist, wie es aussehen sollte:
enter image description here

Dies ist, was tatsächlich geschieht:
enter image description here

ich ein Gefühl, das ich die Elemente falsch ändert offensichtlich etwas oder vielleicht bin fehlt, aber ich habe keine Ideen für diesen. Ich bin nicht ganz neu in C# und UI-Design, aber ich kann nicht sagen, dass ich auch alle wichtigen Steuerungsvorgänge kenne. Jede Hilfe wäre sehr willkommen.

EDIT 1: Dies ist ein Beispielformular, das das Problem reproduzieren sollte. Ich fange einen Verdacht zu haben, dass etwas String mit dem Update Teil zu tun haben könnte, aber es wird sich auch in den btnAdd_Click Code verwendet ...

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

nicht reproduzieren kann. Durch Ändern eines ListBox-Elements wird der Bildlaufleistenbereich geändert. – LarsTech

+0

Gibt es eine Möglichkeit, den Scrollbar-Bereich zu verfolgen, damit ich ihn selbst debuggen kann? Ein nicht öffentliches Eigentum vielleicht? Ich würde mehr Code zur Verfügung stellen, aber ich denke nicht, dass der Rest relevant ist. Ich durchlaufe jeden Listeneintrag, um sie zu aktualisieren, aber das ist der Umfang des relevanten externen Codes. Edit: Es kann helfen, zu wissen, dass diese Operationen nicht im selben Objekt wie die Listbox ausgeführt werden, weshalb es öffentlich ist. – covertCoder

+0

Tun Sie es andersherum. Erstellen Sie ein neues Projekt und reproduzieren Sie das Problem mit der minimalen Menge an Code. Sende diesen Code.Sie betrachten Code, den niemand sonst sehen kann, was es schwer macht, Ihnen zu helfen. – LarsTech

Antwort

2

Das Problem mit den Ampersand Zeichen zu sein scheint . Wenn Sie das Objekt hinzufügen, scheint es korrekt zu messen. Wenn Sie das Element aktualisieren, tut es dies nicht.

Dieser hässliche Hack scheint zu sein: notieren Sie den Index, entfernen Sie den Artikel, fügen Sie den Artikel wieder in diesen aufgezeichneten Index ein.

Oder wechseln Sie zu DrawMode = OwnerDrawFixed und berechnen Sie den HorizontalExtent Wert für jedes Element, das Sie hinzufügen oder ändern.

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

Leider würden Sie es für jede Änderung rufen müssen:

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

Hier ist eine schnelle und schmutzige DrawItem Version:

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

Wow, das ist großartig! Ich werde das durcharbeiten und Sie wissen lassen, wie es läuft. Mir geht es gut mit 'hässlichem' Code, solange es C# 's Bug ist, mit dem es aussieht, wie es ist. – covertCoder

+0

Funktioniert wie ein Charme (ResizeListBox() zumindest), vielen Dank für Ihre Zeit und Mühe LarsTech. – covertCoder

+1

Ich musste TextFormatFlags.SingleLine | verwenden TextFormatFlags.NoPrefix in TextRenderer.MeasureText(), damit es funktioniert. – huha