none
DataGridView an ein TabelLayoutPanel anpassen RRS feed

  • Frage

  • Hallo Forum,

    ich habe ein DataGridView in einem TabelLayoutPanel mit der Eigenschaft Dock "Fill".

    "Leider" ist der Platz im TabelLayoutPanel größer als das es die Daten im DataGridView benötigen. Wie kann ich die Spaltenbreite so anpassen, das die ganze Länge des TabelLayoutPanel  genutzt wird. Besonders beim ziehen / vergrößern des Fensters sieht das nicht gut aus. Die Daten hängen dan so in einer Ecke.

    Auch die Anzahl der Zeilen reicht nicht unbedingt aus, um den Platz der im TabelLayoutPanel zu verfügung steht zu füllen. Da wäre es schön wenn man den restlichen Platz durch "leere" Zeilen auffüllen könnte.

    Die Schriftgröße und die Feldhöhe sollte aber nicht größer werden. Die Felder sollen einfach breiter werden. Geht sowas ?

    Gruß Roland

    Freitag, 10. September 2010 05:40

Antworten

  • Hallo Roland,

    um dass selbständig erweitern zu können (alles kann ich Dir nicht abnehmen ;-)
    solltest Du Dich mit Xml im allgemeinen und LINQ To Xml im besonderen beschäftigen.

    Die Idee ist im übrigen nicht neu.
    Windows Forms benutzt etwas ähnliches für seine Ressourcen (siehe u. a. .RESX zu den Formularen).
    Und in WPF kann man mit XAML ein komplettes Formular damit erstellen.

    Selbst sollte man jedoch kleinere Brötchen backen, wenn man in absehbarer Zeit
    damit fertig werden will.

    Wenn Du Dir das bisherige anschaust:

     

    <Einstellungen>
     <Control ControlName="customersDataGridView">
      <Columns>
       <Column ColumnName="dataGridViewTextBoxColumn1" DisplayIndex="0" Visible="true" Width="77" />
       <Column ColumnName="dataGridViewTextBoxColumn2" DisplayIndex="1" Visible="true" Width="223" />
       <Column ColumnName="dataGridViewTextBoxColumn3" DisplayIndex="2" Visible="true" Width="264" />
       <Column ColumnName="dataGridViewTextBoxColumn4" DisplayIndex="3" Visible="true" Width="100" />
       <Column ColumnName="dataGridViewTextBoxColumn5" DisplayIndex="4" Visible="true" Width="100" />
       <Column ColumnName="dataGridViewTextBoxColumn6" DisplayIndex="5" Visible="true" Width="100" />
       <Column ColumnName="dataGridViewTextBoxColumn7" DisplayIndex="6" Visible="true" Width="5" />
       <Column ColumnName="dataGridViewTextBoxColumn8" DisplayIndex="7" Visible="true" Width="100" />
       <Column ColumnName="dataGridViewTextBoxColumn9" DisplayIndex="8" Visible="true" Width="100" />
       <Column ColumnName="dataGridViewTextBoxColumn10" DisplayIndex="9" Visible="true" Width="100" />
       <Column ColumnName="dataGridViewTextBoxColumn11" DisplayIndex="10" Visible="true" Width="101" />
      </Columns>
     </Control>
    </Einstellungen>
    
    was man im übrigen auch (ab SQL Server 2005) im SSMS abfragen kann:
    SELECT PersonId, FormularName, CAST(Einstellungen AS xml)
    FROM dbo.GridEinstellungen
    

    so habe ich vom Prinzip Platz für beliebige viele Steuerelemente gelassen.

    Will man es für ein Formular insgesamt verwenden, sollte man die Hierarchie
    dort entsprechend nachstellen, das könnte grob skizziert etwas sein wie:

    <Einstellungen>
     <Form Name="CustomerGridForm">
     <Controls>
    	<Control ControlName="customersDataGridView">
    		<Columns>
    		</Columns>
        </Control>
    	<Control ControlName="loadLayoutButton"/>
    	<Control ControlName="saveLayoutButton"/>
     <Controls>
    </Einstellungen> 
    

    Nicht berücksichtigt ist dabei, dass tiefere Schachtelungen existieren können,
    wie zusätzliche Panels, UserControls uam.
    Wobei es nur das Gerüst wäre, welche Eigenschaften Du dort einbaust,
    bleibt Deinen Ansprüchen überlassen.

    Einiges weitere im anderen Thread...

    Gruß Elmar

    Donnerstag, 16. September 2010 09:04

Alle Antworten

  • Hallo Roland,

    schau Dir mal an: Größenanpassung bei Spalten und Zeilen im DataGridView-Steuerelement in Windows Forms
    dort werden die verschiedenen Möglichkeiten beschrieben.

    Gruß Elmar

    Freitag, 10. September 2010 07:14
  • Hallo Elmar,

    Danke. Habe einiges gefunden, aber leider noch nicht zu :

    Auch die Anzahl der Zeilen reicht nicht unbedingt aus, um den Platz der im TabelLayoutPanel zu verfügung steht zu füllen. Da wäre es schön wenn man den restlichen Platz durch "leere" Zeilen auffüllen könnte.

    Hast Du mir da noch einen Hinweis ?

    Fruß Roland

    Freitag, 10. September 2010 13:03
  • Hallo Roland,

    das ist nicht wirklich vorgesehen und das Einfügen von Leerzeilen würde bestenfalls im
    ungebundenen Szenario (ala Excel) klappen, siehe
    Gewusst wie: Erstellen eines ungebundenen DataGridView-Steuerelements in Windows Forms

    Sobald Du Datenbindung hast, wovon ich anhand Deiner vorherigen Fragen ausgehe,
    kann man davon nur dringend abraten. Man programmiert sich schnell einen Wolf ;-))
    was in keinem Verhältnis zur "verbesserten Optik" steht.

    Da sollte man eher eine neutralere Hintergrundfarbe als AppWorkSpace wählen.

    Gruß Elmar

    Freitag, 10. September 2010 14:02
  • Hallo Elmar,

    habe das DataGrid von "Hand" erstellt, also die Spalten so defineirt wie ich es brauche. Habe jetzt aber das nächste Proglem. Habe die DataTable xx bisher mit dem Befehl datagrid1.source = xx; angebunden. Wie kann ich jetzt von "Hand" die Felder in der DataTabel den einzelnen Spalten im DatGrid zuordnen ? Die Reihenfolge hab ich jetzt auch geändert. Soll bedeuten die Feldfolge in der Tabel ist nicht die Reihenfolge im Grid. 

    Gruß Roland

    Freitag, 10. September 2010 20:44
  • Hallo Roland,

    das habe ich mit "einen Wolf programmieren" gemeint:
    Wenn Du das ganze ungebunden machst, darfst Du die Werte manuell in das Grid verfrachten,
    Änderungen selbst nachverfolgen und sie zurück in die DataTable verfrachten.
    Hilfestellung von der Datenbindung gibt es keine mehr.

    Und wie im anderen Beitrag gestern geäussert und hier wiederholt:
    Wer sich auf eine Zeilen/Spalten-Reihenfolge in einer DataTable verlässt,
    wird über  kurz oder lang verlassen und wird mit einer IndexOutOfRangeException
    oder anderen Ausnahmen daran erinnert.

    Da ich vermute das ganze gehört von der Aufgabenstellung zum Thread
    DataTabel direkt auf ein Feld "Springen"
    möchte ich hier nicht weiter darauf eingehen.

    Ich empfehle Dir hier: Passe die Einstellungen des DataGridViews unter Darstellung an,
    so dass es Deinem Empfinden passt (und auch Deinen Kunden gefallen mag).
    Über BackgrounColor kannst Du den dunklen Standard-Hintergrund aufhellen
    (sei es ControlLight, Window oder individuelle Farben).
    Durch Eigenschaften wie RowsDefaultCellStyle, AlternatingRowsDefaultCellStyle
    CellBorderStyle usw. kann man die Optik weniger uniform aussehen lassen.

    Gruß Elmar

    Samstag, 11. September 2010 08:16
  • Hallo Elmar, Danke für die Anwort, aber mit Anpassen hab ich das nicht so extrem gemeint. Habe die Überschriften der Spalten im Grid so gemacht das man sie Versteht. Die Feldnamen sind nicht immer verständlich. Die Reihenfole und die Größe der Spalten hab ich an das TabelLayoutPanel gebunden. Ausserdem möchte ich noch eine CheckBox und eine ComboBox einbinden. Habe zum Beispiel ganz links im Grid die Material Nr. im DataTabel xx ist die MatNr aber an der 8ten Stelle. Die Frage ist, wie kann ich die Tabellenfelder den Spalten zuordnen ? Gruß Roland
    Samstag, 11. September 2010 21:31
  • Hallo Roland,

    ob extrem oder nicht, ich bin mir nicht sicher, dass ich nachvollziehen kann,
    was Du da gemacht hast.

    Um Überschriften und Größen anzupassen, braucht man das DataGridView
    nicht im ungebundenen Modus betreiben (wie oben zumindest geschrieben).

    Für jede Spalte wird eine DataGridViewColumn vom spezialisierten Typ angelegt -
    z. B. DataGridViewTextBoxColumn, DataGridViewComboBoxColumn usw...

    Die kann man zur Entwurftzeit aber auch zur Laufzeit anpassen -
    vergleichbar mit dem, was Du es im anderen Beitrag vorhast.

    In Falle der Datenbindung wird über die DataPropertyName Eigenschaft der Wert der Datenquelle
    entnommen. Willst Du nun ungebunden arbeiten müsstest Du das nachprogrammieren.

    Nur kann ich nicht so ganz ermitteln, was Du da wirklich gemacht hast...

    Es wäre schön, wenn Du Dich präziser erklären würdest -
    bedenke ich schaue nicht den ganzen Tag auf Dein Projekt.

    Gruß Elmar

    Montag, 13. September 2010 14:35
  • Hallo Elmar,

    Danke für die Antwort.

    Eigentlich wollte ich erst mal noch etwas mit den Grids "spielen", aber wenn Du mich schon so frägst. In einer anderen Programmiersprache habe ich folgendes gemacht und möchte das eigentlich auch so beibehalten ( gute Erfahrungen ). Machen wir das an einem Beispiel für ein Grid "Materialstamm" fest.

    Die Standard Reihenfolge der anzuzeigenden Felder >>Column.Header.Text // Material Nummer, Material Bezeichnung, EK Preis, VK Preis, Freier Lagerbestand, . . .Dann noch ein Button "Details" mit dem man weitere Informationen abrufen kann.

    Diese Informationen (Felder) lade ich aus einer MS SQL DB in ein DataTabel "xx". Nun möchte ich das DataTabel Feld "xx.MatNr" der Spalte "Material Nummer" (Column.Name "MatNr" ) im Grid zuordnen. Das DataTabel Feld "xx.MatBez" der Spalte "Material Bezeichnung" (Column.Name "MatBez1" ) im Grid zuordnen, u.s.w.

    Der Benuztzer hat / soll aber die Möglichkeit haben die Breite und die Position der Spalten zu ändern. Diese geänderten Einstellungen möchte ich speichern, aber nicht lokal sondern in der SQL DB in einer Tabelle "yy" ( die Mitarbeiter haben keinen festen PC sind alle im Aussendienst ( 60 Pers. ) und müssen dann im Büro den PC ( 16 St. ) nehmen der frei ist).

    Momentan mache ich das so, das ich in einer DB Tabelle einen Datensatz "STD" habe der die "normale" Reihenfolge und Größe der Spalten beschreibt.

    Ändert ein Mitarbeiter die Breite oder Position einer Spalte ab, speicher ich die Informationen zu allen Spalten beim Verlassen der Maske für den Mitarbeiter unter dessen PersNr in der DB Tabelle als Datensatz ab.

    Meldet sich der Mitarbeiter an, kontrolliere ich ob es für seine PersNr einen Datensatz gibt, wenn ja wird das Grid nach diesen Einträgen aufgebaut, wenn nicht nach den "STD" Vorgaben. Dadurch kann ich die pers. Einstellungen für den Mitarbeiter an jedem PC darstellen. Ausserdem kann ich wenn nötig die "STD" Einstellung ohne Aufwand jederzeit mit einem Eintrag anpassen. ( z.B. neue Felder mit anzeigen )

    Für mich stellen sich jetzt folgende Fragen.

    1. wie kann ich die Colums einers Grids in einer Schleife auslesen ? (Column.Name, Breite und Position ) und in einem String Speichern Format >MatNr,120,1,MatBez,x,x,...<

    2. wie kann ich in einer Schleife die Felder aus der DataTabel xx den entsprechenden Colums im Grid zuorden. ( DataTabel "xx.MatNr" >> Grid Column "Material Nummer" )

    Hoffe das dies jetzt verständlicher ist.

    Hast dazu eine Idee ?

    Gruß Roland

    Dienstag, 14. September 2010 06:43
  • Hallo Roland,

    Das Konzept ist schon in Ordnung, nur sollte man es der Umgebung anpassen.
    Und die Möglichkeiten nutzen, wo sie ein mehr an Flexibilität bieten.

    Wenn es denn nun das DataGridView anstatt der Buttons sein soll,
    so ist mir das auch Recht. Ich habe mal ein Beispiel dafür erstellt:

    http://www.elmarboye.de/download/GridLayoutSettings.zip

    Als Datenquelle für das DataGridView verwende ich die Northwind.Customers Tabelle.
    Für den Test mußt Du die Verbindungseintellungen in den Eigenschaften->Einstellungen anpassen.
    Für die indiviuelle PersonID habe ich ebenfalls auf die Eigenschaften zurückgegriffen.

    Für die Einstellungen selbst verwende ich XLinq , um variable Eigenschafszuordnungen zu realisieren.
    So spart man sich spezielle Definitionen für jede einzelne Eigenschaft,
    die in .NET deutlich reichhaltiger ausfallen können.

    Das Konzept wäre für beliebige andere Steuerelemente bis hin zu ganzen Formularen denkbar.
    Wofür noch einige Zeilen Code mehr notwendig wären, aber Du sollst ja noch was zu tun haben ;-)

    Gruß Elmar

    Dienstag, 14. September 2010 11:28
  • Hallo Elmar,

    vielen Danke für die ausführliche Hilfe und das Testprogramm. Habe mir das ganze mal kurz angesehen. Da muss ich noch einiges lernen um das zu verstehen. Werde mich damit gleich morgen ausführlich beschäftigen.

    Da kommen sicherlich noch einige Fragen.

    Gruß Roland

    Mittwoch, 15. September 2010 06:36
  • Hallo Elmar,

    habe mir den Code angesehen und auch schon wieder eine Idee. Ich möchte nicht für jedes Objekt einen Datensatz erstelln, sonder für definierte Objekt in einer Form nur ein XDokument. Dazu habe schon die erste Frage.

    Dein Code erstellt für 1 Objekt ein XDocument. Habe mir nun eine Tabelle (im public Teil ) erstellt, in der ich die Objekte eintrage die gespeichert werden sollen.

    Nun möchte ich diese in einer Schleife durchlaufen. Wie muss ich deinen Code abändern um alle Objekte in ein XDokument einzutragen. Muss dazu sagen, habe mit der Art der Datenspeicherung noch nie was gemacht. Dürfte also eine Anfängerfrage sein. Aber die Idee das so zu tun hat mich echt überzeugt.

    var columquery = from column in GridUebersicht.Columns.Cast<DataGridViewColumn>() 
    select new XElement("Column", new XAttribute("ColumnName", column.Name), new XAttribute("DisplayIndex", column.DisplayIndex), new XAttribute("Visible", column.Visible), new XAttribute("Width", column.Width)); 
    var document = new XDocument(new XElement("Einstellungen", new XElement("Control", new XAttribute("ControlName", GridUebersicht.Name.ToString()), new XElement("Columns", columquery.ToArray()))));

    Gruß Roland

    Donnerstag, 16. September 2010 07:27
  • Hallo Roland,

    um dass selbständig erweitern zu können (alles kann ich Dir nicht abnehmen ;-)
    solltest Du Dich mit Xml im allgemeinen und LINQ To Xml im besonderen beschäftigen.

    Die Idee ist im übrigen nicht neu.
    Windows Forms benutzt etwas ähnliches für seine Ressourcen (siehe u. a. .RESX zu den Formularen).
    Und in WPF kann man mit XAML ein komplettes Formular damit erstellen.

    Selbst sollte man jedoch kleinere Brötchen backen, wenn man in absehbarer Zeit
    damit fertig werden will.

    Wenn Du Dir das bisherige anschaust:

     

    <Einstellungen>
     <Control ControlName="customersDataGridView">
      <Columns>
       <Column ColumnName="dataGridViewTextBoxColumn1" DisplayIndex="0" Visible="true" Width="77" />
       <Column ColumnName="dataGridViewTextBoxColumn2" DisplayIndex="1" Visible="true" Width="223" />
       <Column ColumnName="dataGridViewTextBoxColumn3" DisplayIndex="2" Visible="true" Width="264" />
       <Column ColumnName="dataGridViewTextBoxColumn4" DisplayIndex="3" Visible="true" Width="100" />
       <Column ColumnName="dataGridViewTextBoxColumn5" DisplayIndex="4" Visible="true" Width="100" />
       <Column ColumnName="dataGridViewTextBoxColumn6" DisplayIndex="5" Visible="true" Width="100" />
       <Column ColumnName="dataGridViewTextBoxColumn7" DisplayIndex="6" Visible="true" Width="5" />
       <Column ColumnName="dataGridViewTextBoxColumn8" DisplayIndex="7" Visible="true" Width="100" />
       <Column ColumnName="dataGridViewTextBoxColumn9" DisplayIndex="8" Visible="true" Width="100" />
       <Column ColumnName="dataGridViewTextBoxColumn10" DisplayIndex="9" Visible="true" Width="100" />
       <Column ColumnName="dataGridViewTextBoxColumn11" DisplayIndex="10" Visible="true" Width="101" />
      </Columns>
     </Control>
    </Einstellungen>
    
    was man im übrigen auch (ab SQL Server 2005) im SSMS abfragen kann:
    SELECT PersonId, FormularName, CAST(Einstellungen AS xml)
    FROM dbo.GridEinstellungen
    

    so habe ich vom Prinzip Platz für beliebige viele Steuerelemente gelassen.

    Will man es für ein Formular insgesamt verwenden, sollte man die Hierarchie
    dort entsprechend nachstellen, das könnte grob skizziert etwas sein wie:

    <Einstellungen>
     <Form Name="CustomerGridForm">
     <Controls>
    	<Control ControlName="customersDataGridView">
    		<Columns>
    		</Columns>
        </Control>
    	<Control ControlName="loadLayoutButton"/>
    	<Control ControlName="saveLayoutButton"/>
     <Controls>
    </Einstellungen> 
    

    Nicht berücksichtigt ist dabei, dass tiefere Schachtelungen existieren können,
    wie zusätzliche Panels, UserControls uam.
    Wobei es nur das Gerüst wäre, welche Eigenschaften Du dort einbaust,
    bleibt Deinen Ansprüchen überlassen.

    Einiges weitere im anderen Thread...

    Gruß Elmar

    Donnerstag, 16. September 2010 09:04