Programmatically resize a column in a Windows Forms property grid control

Using the standard Microsoft .NET 2.0 WinForms PropertyGridControl control, I was looking for a way to set the size of the two columns (one for the labels, one for the values) so that I can control better how the values are displayed.

After some research with ILSpy on the .NET sources, I found a way to use with reflection. The following helper method can be used for this task:

public static void ResizePropertyGridSplitter(
    PropertyGrid propertyGrid,
    int labelColumnPercentageWidth)
{
    var width =
        propertyGrid.Width*(labelColumnPercentageWidth/100.0);

    // Go up in hierarchy until found real property grid type.
    var realType = propertyGrid.GetType();
    while (realType!=null && realType != typeof(PropertyGrid))
    {
        realType = realType.BaseType;
    }

    var gvf = realType.GetField(@"gridView",
        BindingFlags.NonPublic |
        BindingFlags.GetField |
        BindingFlags.Instance);
    var gv = gvf.GetValue(propertyGrid);

    var mtf = gv.GetType().GetMethod(@"MoveSplitterTo",
        BindingFlags.NonPublic |
        BindingFlags.InvokeMethod |
        BindingFlags.Instance);
    mtf.Invoke(gv, new object[] { (int)width });
}

Call the function and pass your PropertyGrid instance and width values between e.g. 10 and 90 to resize the first column to the given percentage value.

E.g.:

ResizePropertyGridSplitter( myPropGrid, 75 );

If you specify a too small or too large value, the PropertyGrid seems to use the minimum/maximum possible, based on your passed value.

Fehlermeldung „Column does not belong to table“

Bei mir trat/tritt von Zeit-zu-Zeit die Fehlermeldung „Column does not belong to table“ auf, jeweils mit einer angegebenen Spalte, z.B.

Column ‚TestPlanID‘ does not belong to table

Oder

Column ‚ParentID‘ does not belong to table

Bzw. auf Deutsch

Spalte ‚RunnableTestCaseID‘ gehört nicht zu Tabelle

Da das nur teilweise auftritt und nur bei manchen Kunden und nur wenn viele SQL-Anfragen hintereinander ausgeführt werden, hat mir dieser Blogpost hier geholfen.

Der Autor dort geht davon aus, dass er ggf. Connections nicht rechtzeitig schließt. Als er das beseitigt hatte und der Fehler immer noch auftrat, hat er folgende Schlussfolgerungen/Aktionen daraus gezogen:

  1. Use „iisreset“ command every time you stop the IIS server.
  2. Walk through your code and make sure you are closing connection properly.
  3. Use „Connection Lifetime“ property of connection pool if required.
  4. Try to use ClearAllPools/ClearPool in appropriate application event.

Bei mir hat das teilweise geholfen, ggf. ist das ja doch irgend ein .NET-Bug, der irgendwann mal mit den neuesten Treibern für Microsoft SQL Server beseitigt sind.

Ergänzung 1:

Gerade heute bekomme ich wieder eine ähnliche Meldung bei einem Oracle-Projekt:

Column „FACH“ does not belong to table

Ich deute das so, dass das auch beim Oracle-Treiber so ein Issue ist. Es handelt sich hier um eine ASP.NET-4.0-Webanwendung. Andere sprechen auch darüber, dass es bei Ihnen auch bei Oracle auftritt. Vermutlich also ein Issue in ADO.NET. Einer schreibt:

We had this exact problem and we solved it.

Using static (C#) or shared (VB) .Net data classes on a multi-processor server will cause this error. The data class and its objects, e.g. DataTable, get resused across threads for some reason. So when when two requests come in at the same time, the second request overwrote the DataTable object variable with its own results, causing the first request to fail when it went looking for its tables, columns, etc.

This problem only occurred on multi-processor servers and went away when we declared our data classes without static or shared.

Wobei ich ihm das nicht ganz glaube. der Oracle provider hat auch eine Funktion ClearAllPools/ClearPool, diese werde ich jetzt mal aufrufen.

Ergänzung 2:

Den Fehler konnte ich jetzt beim Oracle erfolgreich beseitigen, indem ich meinen (eigenen) Cache deaktiviert habe. Eventuell hängt es mit dem Background-Cache-Aufräumen zusammen oder mit zu vielen Elementen im Cache.

Ergänzung 3 (2013-04-22):

Hatte jetzt erneut so einen Fall, den ich durch Cache-Deaktivieren lösen konnte.

Eventuell ist es ja sinnvoll, wenn eine DataTable aus dem Cache geholt wird, diese zu clonen, so dass nur die gleiche, nicht jedoch dieselbe DataTable genutzt wird und es so nicht zu Concurrency-Issues kommen kann. (Habe das jetzt probiert, hat in meinen Tests keine Änderung gebracht, leider).