MaximumWidth pro DataGridViewColumn

Otázky a odpovědi. Při hledání vhodného řešení si občas člověk užije a prověří svoje schopnosti. Ne vždy je odpovědí optimální řešení, ale jak nás učili na škole, lepší vybírat mezi suboptimálním řešením, než žádným. A právě jedna taková otázka se objevila na builderu, týkala se maximální šířky sloupečku v DataGridView. Jelikož jsem se při odpovědi maličko více rozepsal, rozhodl jsem se odpověď uveřejnit jako příspěvek.

Možné řešení maximální šířky sloupce je celkem prosté a vycházím z toho, že DataGridView publikuje několik událostí při změně šířky sloupečku. Zároveň je však důležité přidat do definice sloupce informaci, zda má sloupec povolenu max. šířku a případně její hodnotu.

SizingDataGridViewTextBoxColumn

Nejdříve jsem si tedy vytvořil potomka po DataGridViewTextBoxColumn a přidal jsem mu vlastnost MaximumWidth, která uchovává hodnotu o maximální šířce sloupečku. Dále bylo nutné přepsat metodu GetPreferredWidth, tak aby tato vracela požadovanou šířku v daných případech.

SizingDataGridView

Dále jsem podědil třídu DataGridView, kde bylo nutné přepsat dvě metody, ke kterým dochází v průběhu změny šířky sloupce. Jedná se o metody OnColumnDividerDoubleClick a OnColumnWidthChanged.

Proto, abych si ulehčil maličko práci a výsledný kód splňoval alespoň nějaké podmínky pro rozšíření jsem dodefinoval ještě interface, který implementují všechny sloupečky, které mají mít nastavenu maximální šířku. Nazval jsem jej ISizingDataGridViewColumn. Na toto rozhraní se odvolávám právě u obou přepsaných metod.

Zdrojové kódy

Ještě zbývá uvést zdrojové kódy jednotlivých, zde zmíněných tříd a interface. Jelikož se jedná o poměrně malé části kódu, uvádím je v plném znění bez komentářů.

ISizingDataGridViewColumn:
public interface ISizingDataGridViewColumn
{
  int MaximumWidth { get; set; }
}
SizingDataGridViewTextBoxColumn:
public class SizingDataGridViewTextBoxColumn : DataGridViewTextBoxColumn, ISizingDataGridViewColumn
{
  private int _maximumWidth;
             
  public int MaximumWidth
  {
    get { return _maximumWidth; }
    set
    {
      if (_maximumWidth != value)
      {
        _maximumWidth = value;
      }
    }
  }

  public override int GetPreferredWidth(DataGridViewAutoSizeColumnMode autoSizeColumnMode, bool fixedHeight)
  {
    int width = base.GetPreferredWidth(autoSizeColumnMode, fixedHeight);
    int currWidth = this.Width;
    if (MaximumWidth < width)
    {
      width = MaximumWidth;
    }
    if (currWidth > width)
    {
      return width;
    }
    return currWidth;
  }
}

SizingDataGridView

public class SizingDataGridView : DataGridView
{
  protected override void OnColumnDividerDoubleClick(DataGridViewColumnDividerDoubleClickEventArgs e)
  {
    if (this.Columns[e.ColumnIndex] is ISizingDataGridViewColumn)
    {
      this.Columns[e.ColumnIndex].Width = ((ISizingDataGridViewColumn)this.Columns[e.ColumnIndex]).MaximumWidth;
    }
    base.OnColumnDividerDoubleClick(e);
  }

  protected override void OnColumnWidthChanged(DataGridViewColumnEventArgs e)
  {
    base.OnColumnWidthChanged(e);
    if (e.Column is ISizingDataGridViewColumn)
    {
      this.AutoResizeColumns();
    }
  }
}
A to je vše. Jak jsem se již zmínil na začátku, určitě se nemusí jednat o řešení optimální, spíše se jedná o nástin možného řešení, které je třeba rozvést a otestovat pro všechny stavy, které mohou u DataGridView nastat.
Add a Comment