Selektives Deaktivieren von Zellen in DGV

  • VB.NET
  • .NET (FX) 4.0

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von VB1963.

    Selektives Deaktivieren von Zellen in DGV

    Hallo Forum,

    ich versuche mich gerade an einer kleinen Datenbank und habe Probleme mit der Darstellung in einem DGV.

    Ich möchte einzelne Zellen meines DGV in Abhängigkeit einer weiteren Zelle re-/deaktivieren. Zum besseren Verständnis habe ich unten mal ein Bild angehängt.

    Wird der boolesche Wert "Auswahl"auf true gesetzt, soll in der selben DataRow die Zelle für "Parameter 1" aktiviert und die Zelle für "Parameter 2" deaktiviert werden. Wird "Auswahl" auf false gesetzt, dann entsprechend anders herum.


    Ich habe jedoch keine Ahnung wie ich selektiv einzelne Zellen im DGV in Abhängigkeit eines Parameters deaktiviere.


    lg

    Edit:
    Nach dem berechtigten Einwand von Rod, habe ich den Startbeitrag mal auf das Wesentliche gekürzt...
    Bilder
    • FakeDGV.JPG

      26,26 kB, 602×171, 121 mal angesehen

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „cl10k“ ()

    @VB1963 Jou.

    cl10k schrieb:

    Zum besseren Verständnis
    hättest Du den Triebwerk-Vortrag weggelassen und das Problem auf Inhalte 1 oder 2 oder 3 reduziert. ;)
    Disable geht praktisch nicht, das musst Du umschippern.
    Sieh Dir mal dieses Snippet an:

    VB.NET-Quellcode

    1. Private Sub DataGridView1_CellFormatting(sender As Object, e As DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
    2. If e.Value Is Nothing OrElse e.Value.GetType <> Type.GetType("System.String") Then
    3. Return
    4. End If
    5. If e.Value.ToString = "ja" Then
    6. e.CellStyle.BackColor = Color.LightBlue
    7. Else
    8. e.CellStyle.BackColor = Color.White
    9. End If
    10. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:



    hättest Du den Triebwerk-Vortrag weggelassen und das Problem auf Inhalte 1 oder 2 oder 3 reduziert.


    Du hast grundsätzlich natürlich recht, ich hielt es für sinnvoll auf den Kontext einzugehen, damit keine Vorschläge kommen hier zusätzliche DataTables/DGV anzulegen. :)

    ---

    Vielen Dank für eure Antworten, ich werde damit ein wenig rumspielen und mich dann wieder melden...
    Ich habe nun eine vorläufige Lösung gefunden die in Ansätzen funktioniert, aber noch ein paar kleine Macken hat.


    Im DGV sind eine CheckBoxColumn(Tristate) und zwei Datenspalten vom Typ Double. Über die Checkbox werden die DoubleColumns wechselseitig (de-) aktiviert. Ist die CheckBox unbestimmt, sind beide Datenspalten aktiv.


    Den Status einer DGV-Zelle schalte ich hiermit um:

    VB.NET-Quellcode

    1. Private Sub ToggleCellDeactivation(ByVal tmpCell As DataGridViewCell, ByVal tmpStatus As Boolean)
    2. tmpCell.ReadOnly = tmpStatus
    3. If tmpStatus = True Then 'Deactivate Cell
    4. tmpCell.Style.BackColor = Color.LightGray
    5. tmpCell.Style.ForeColor = Color.DarkGray
    6. If IsDBNull(tmpCell.Value) Then
    7. tmpCell.Value = -1
    8. End If
    9. Else '(Re)Activate Cell
    10. tmpCell.Style.BackColor = tmpCell.OwningColumn.DefaultCellStyle.BackColor
    11. tmpCell.Style.ForeColor = tmpCell.OwningColumn.DefaultCellStyle.ForeColor
    12. If tmpCell.Value.ToString() = "-1" Then 'Clumsy, but Doubles should not be compared to -1
    13. tmpCell.Value = DBNull.Value
    14. End If
    15. End If
    16. End Sub


    Da ich im zugehörigen DataTable generell AllowDBNull=False habe, schreibe ich in deaktivierte leere Zellen zeitweilig eine "-1" damit keine Exception fliegt.


    Nun zu den Problemen:

    1) Um rauszufinden wann eine CheckBox geklickt wurde, nutze ich das CellContentClick-Event. Das funktioniert aber leider nicht zuverlässig. Klickt der Anwender schnell genug auf die CheckBox wird nicht jedesmal ein Event gefeuert. Welche Alternativen bleiben mir (ohne erst über einen Fokusverlust die Zellvalidierung anzustossen)?

    2) DGVs speichern scheinbar keine Zellformatierung. Sobald der Anwender z.B. umsortiert oder einen Load/Safe-Vorgang anstösst, verlieren alle Zellen ihre Farben. Ich habe nicht zweifelsfrei das Event identifizieren können, dass in den entsprechenden Situation gefeuert wird. Momentan aktualisiere ich die Formatierung über das DataBindingComplete-Event. Das feuert nur sehr selten und scheint ganz gut zu passen, habt ihr einen besseren Vorschlag?

    3) Mein Quellcode ist bestenfalls plump. Wenn ihr Lust habt, schaut doch mal in das angehängte Projekt (VS2015CE) und gebt ein paar Tipps was man eleganter machen könnte. (Der Quellcode ist Teil eines größeren Projekts. Auf ExceptionHandling habe ich daher hier mit Absicht verzichtet...)


    -------------------------------------------------------------
    An dieser Stelle sei der Doppelpost bitte verziehen, ich glaube bei einem Edit gäbe es keine erneute Benachrichtigung, oder?
    Bilder
    • DGV.JPG

      43,4 kB, 831×392, 141 mal angesehen
    Dateien

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „cl10k“ ()

    mach sowas doch im CellPainting

    VB.NET-Quellcode

    1. [/size]
    2. Private _PaintedColumns As New List(Of Integer) From {2, 3}
    3. Private Sub DGV_Main_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles DGV_Main.CellPainting
    4. If Not _PaintedColumns.Contains(e.ColumnIndex) Then Return
    5. If e.RowIndex < 0 OrElse e.RowIndex > DGV_Main.RowCount - 2 Then Return
    6. Dim cll = DGV_Main(e.ColumnIndex, e.RowIndex)
    7. Dim rw = DirectCast(DirectCast(DGV_Main.Rows(e.RowIndex).DataBoundItem, DataRowView).Row, dt_TestRow)
    8. If rw.IsChooseWiselyNull Then Return
    9. If rw.ChooseWisely = (e.ColumnIndex = 2) Then Return
    10. e.Graphics.FillRectangle(Brushes.Silver, e.CellBounds)
    11. e.PaintContent(e.CellBounds)
    12. e.Handled = True
    13. End Sub[size=8]
    und natürlich typisiert, und ohne den Deppen-Namespace


    Dateien
    Hallo EDR,

    Danke für dein Beispiel! Es ist immer interessant fremden Code zu sehen, vor allem da ich noch nie was mit Painting gemacht habe. Dein kompakter Ansatz gefällt mir sehr.

    ABER das Problem mit der unzuverlässigen Erkennung der Checkbox besteht noch immer.Mach mal einen Doppelklick auf die Checkbox - dann stimmt die Formatierung der beiden Datenspalten nicht. Was läuft da schief? Kann/muss man einen Doppelklick extra behandeln? (Das mag jetzt nur eine Kleinigkeit sein, aber so ein Doppelklick ist schnell gemacht, vor allem auch weil die Checkbox diese "Tristate" Eigenschaft hat und man leicht versucht ist, den unbestimmten Zustand schnell zu überspringen.)

    ------------------------------------- EDIT -------------------------------------

    CellContentClick feuert nur einmal auch bei einem Doppelklick. Ich habe mich nun stattdessen an CellMouseUp (tritt ein wenn die Maustaste losgelassen wird) gehängt - das klappt tadellos!

    (Hier wird das Problem und die Lösung beschrieben)

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „cl10k“ ()

    Merkwürdig. Ich habe es gerade nochmal ausprobiert und das Doppelklick-Problem existiert hier mit dem Code von EDR (und meinem alten) weiterhin.

    Man kann es auch schön sehen, wenn man per Debug.WriteLine("Klick") das CellContentClick-Event im Output "visualisiert". Doppeklicken schaltet die Checkbox zwar zweimal um, das Event wird aber nur einmal gefeuert. Kann ich hier zu 100% reproduzieren... ?!