Laden...
K
Benutzerbeschreibung
Infos über mich unter www.stangerweb.de

Forenbeiträge von kstanger Ingesamt 99 Beiträge

11.10.2022 - 18:08 Uhr

Hallo allerseits,
ich habe 2 mal ein DataGridView, das per BindingSource mit einer List verbunden ist. Ich will nun im 1. DataGridView Styles verändern, was nicht funktioniert.


            for (int loopFarben = 0; loopFarben < Farben.Count; loopFarben++)
            {
                bool used = false;
                for (int loopLeds = 0; loopLeds < Leds.Count; loopLeds++)
                {
                    if (Leds[loopLeds].Ledfarbname == Farben[loopFarben].Farbname) {
                        used = true;
                        break;
                    }
                }
                if (used)
                {
                    MessageBox.Show(loopFarben.ToString() + ", " + DataGridViewFarben.Rows[loopFarben].Cells[0].Value.ToString());
                    DataGridViewFarben.Rows[loopFarben].Cells[0].Value = 111;
                    MessageBox.Show(loopFarben.ToString() + ", " + DataGridViewFarben.Rows[loopFarben].Cells[0].Value.ToString());
                    DataGridViewFarben.Rows[loopFarben].DefaultCellStyle.Font = new Font(DataGridViewFarben.Font, FontStyle.Bold);
                    DataGridViewFarben.Rows[loopFarben].DefaultCellStyle.ForeColor = Color.Red;
                }
            }

Die 1. MessageBox zeigt die richtigen Werte an -> also Lesen funktioniert.
Die 2. MessageBox zeigt die geänderten Werte an -> also Schreiben funktioniert auch.
Die Style-Zuweisungen funktionieren aber nicht. Warum? Was ist falsch?

10.10.2022 - 18:52 Uhr

Nach langer Suche habe ich jetzt herausgefunden, wie man das Löschen abfangen kann.

  1. In den Eigenschaften des BindingNavigators setzt man unter Elemente DeleteItem auf (keine). Dadurch wird der Standard-Eventhandler für delete abgeschaltet.
  2. Jetzt erzeugt ein Doppelklick auf das Löschen-Symbol des BindingNavigators den Eventhandler
  3. Den Eventhandler füllt man nun mit dem gewünschten Verhalten. Hier ist er für meinen Anwendungsfall:

        private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e)
        {
            bool used = false;
            for (int loop = 0; loop < Leds.Count; loop++)
            {
                if (Leds[loop].Ledfarbname == Farben[BindingSourceFarben.Position].Farbname)
                {
                    used = true;
                    break;
                }
            }
            if (used)
            {
                string message = "Mindestens eine Led hat die Farbe " + Farben[BindingSourceFarben.Position].Farbname
                    + " in Gebrauch. Daher kann die Farbe " + Farben[BindingSourceFarben.Position].Farbname
                    + " nicht gelöscht werden.";
                const string caption = "Löschen nicht erlaubt";
                var result = MessageBox.Show(message, caption, MessageBoxButtons.OK, MessageBoxIcon.Stop);
                return;
            }
            BindingSourceFarben.RemoveCurrent();
        }

Wie soll man darauf kommen?
Ich habe den Tipp hier https://social.msdn.microsoft.com/Forums/en-US/ab77433f-94c5-49c5-9c54-4dd1349d9c2a/bindingnavigator-delete-cancel?forum=vbgeneral gefunden. Selbst dort muss man ca. 2/3 herunterscrollen um den Tipp zu finden.

10.10.2022 - 13:07 Uhr

Das Löschen ist nicht das Problem: das macht der BindingNavigator. Aber in dem 2. DataGridView wird das erste per ComboBox verknüpft. Genau das wirft dann eine Exception: "Der DataGridViewComboBoxCell-Wert ist ungültig", was ja logisch ist. Ich muss also beim Löschen in dem 1. DataGridView sicherstellen, dass diese Daten nicht in dem 2. DataGridView gebraucht werden. Ich muss also das Löschen abfangen und erst erlauben, wenn die entsprechenden daten nicht im 2. benötigt werden.
Da habe ich mein erstes Problem: Wie fange ich das ab?

09.10.2022 - 16:53 Uhr

Hallo,
ich habe ein DataGridView -> BindingSource -> Liste von Objekten. In einem 2. DataGridView werden einige der Daten (einige Zeilen) aus dem 1. DataGridView verknüpft. Jetzt möchte ich z.B. per ausgrauen darstellen, welche Zeilen im 1. DataGridView im 2. nicht gebraucht werden. Der User soll dann die Möglichkeit haben, die nicht gebrauchten Daten zu löschen.
Wie geht so etwas?

09.10.2022 - 16:45 Uhr

Noch ein Update. Statt

    BindingSourceLed.Insert(rowIndexOfItemUnderMouseToDrop, BindingSourceLed.Current);  
    BindingSourceLed.RemoveCurrent();  
    BindingSourceLed.EndEdit();  
    DataGridViewLed.Rows[rowIndexOfItemUnderMouseToDrop].Selected = true;

hier die Verbesserung


                rowIndexFromMouseDown = BindingSourceLed.Position;
                BindingSourceLed.Insert(rowIndexOfItemUnderMouseToDrop, BindingSourceLed.Current);
                if (rowIndexFromMouseDown > rowIndexOfItemUnderMouseToDrop)
                {
                    BindingSourceLed.RemoveAt(rowIndexFromMouseDown + 1);
                    BindingSourceLed.Position = rowIndexOfItemUnderMouseToDrop;
                }
                else
                {
                    BindingSourceLed.RemoveAt(rowIndexFromMouseDown);
                    BindingSourceLed.Position = rowIndexOfItemUnderMouseToDrop - 1;
                }                
                BindingSourceLed.EndEdit();


08.10.2022 - 15:59 Uhr

Ich habe herausgefunden, wie es (zumindest in meinem Fall) funktioniert. Da dies von allgemeinem Interesse sein könnte, hier nochmal der Code.
Voraussetzung: DataGridViewLed hat BindingSourceLed. BindingSourceLed hat Objekt Led.


private Rectangle dragBoxRectFromMouseDown;
private int rowIndexFromMouseDown;
private int rowIndexOfItemUnderMouseToDrop;

private void DataGridViewLed_DragOver(object sender, DragEventArgs e)
{
     e.Effect = DragDropEffects.Move;
 }

private void DataGridViewLed_MouseMove(object sender, MouseEventArgs e)
{
    if (Convert.ToBoolean(Convert.ToInt32(e.Button) == Convert.ToInt32(MouseButtons.Left)))
    {
        if (dragBoxRectFromMouseDown != Rectangle.Empty && !dragBoxRectFromMouseDown.Contains(e.X, e.Y))
        {
            DragDropEffects dropEffect = DataGridViewLed.DoDragDrop(DataGridViewLed.Rows[rowIndexFromMouseDown],DragDropEffects.Move);
         }
     }
}

private void DataGridViewLed_MouseDown(object sender, MouseEventArgs e)
{
   rowIndexFromMouseDown = DataGridViewLed.HitTest(e.X, e.Y).RowIndex;
   if (rowIndexFromMouseDown != -1)
   {
       Size dragSize = SystemInformation.DragSize;
       dragBoxRectFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)), dragSize);
     }
     else
     {
          dragBoxRectFromMouseDown = Rectangle.Empty;
     }
}

private void DataGridViewLed_DragDrop(object sender, DragEventArgs e)
{
    // The mouse locations are relative to the screen, so they must be converted to client coordinates.
    Point clientPoint = DataGridViewLed.PointToClient(new Point(e.X, e.Y));
    rowIndexOfItemUnderMouseToDrop = DataGridViewLed.HitTest(clientPoint.X, clientPoint.Y).RowIndex;
    if (e.Effect == DragDropEffects.Move)
    {
        BindingSourceLed.Insert(rowIndexOfItemUnderMouseToDrop, BindingSourceLed.Current);
        BindingSourceLed.RemoveCurrent();
        BindingSourceLed.EndEdit();
        DataGridViewLed.Rows[rowIndexOfItemUnderMouseToDrop].Selected = true;
     }
}

Kommentare sind erwünscht - bestimmt können noch Dinge verbessert werden.

07.10.2022 - 19:15 Uhr

Hallo,
ich habe ein DataGridView, in dem ich ganze Zeilen mit FullRowSelect auswähle. Ich habe eine BindingSource (BindingSourceLed) und daran dann ein eine Liste von Datenobjekten. Jetzt soll der User zusätzliche Zeilen einbringen, die immer am Ende der Liste eingefügt werden (das funktioniert bereits). Es soll aber möglich sein, einzelne Zeilen per Drag&Drop beliebig in der Liste zu verschieben.
Ich habe bereits danach gesucht und etwas gefunden, das die Ereignisse DragEnter, MouseMove, MouseDown und DragDrop bedient. Ich denke, dass ich den Fehler durch die Datenbindung erzeuge.


        private void DataGridViewLed_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }

        private void DataGridViewLed_CellMouseMove(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (Convert.ToBoolean(Convert.ToInt32(e.Button) == Convert.ToInt32(MouseButtons.Left)))
            {
                if (mdrRect != Rectangle.Empty && !mdrRect.Contains(e.X, e.Y))
                {
                    DataGridViewRow DGVR = DataGridViewLed.Rows[mdrIndex];
                    DragDropEffects DDF = DataGridViewLed.DoDragDrop(DGVR, DragDropEffects.Move);
                }
            }
        }
        private void DataGridViewLed_MouseDown(object sender, MouseEventArgs e)
        {
            mdrIndex = DataGridViewLed.HitTest(e.X, e.Y).RowIndex;

            if (mdrIndex != -1)
            {
                Size ds = SystemInformation.DragSize;
                mdrRect = new Rectangle(new Point(e.X - Convert.ToInt16((ds.Width / 2)), e.Y - Convert.ToInt16((ds.Height / 2))), ds);
            }
            else
            {
                mdrRect = Rectangle.Empty;
            }
        }

        private void DataGridViewLed_DragDrop(object sender, DragEventArgs e)
        {
            Point ptc = DataGridViewLed.PointToClient(new Point(e.X, e.Y));
            Int32 index = DataGridViewLed.HitTest(ptc.X, ptc.Y).RowIndex;
            if (e.Effect == DragDropEffects.Move)
            {
                DataGridViewRow RowToMove = e.Data.GetData(typeof(DataGridViewRow)) as DataGridViewRow;
                //DataTable tb = DataGridViewLed.DataSource as DataTable;
                //DataRow row = tb.Rows[mdrIndex];
                //tb.Rows.RemoveAt(mdrIndex);
                //tb.Rows.InsertAt(row, index);
                //tb.AcceptChanges();

/*  Ich denke, dass ich diese Zeilen nicht brauche, da meine BindingSource das erledigt.              
                DataGridViewLed.Rows[index].Selected = true;
                for (int i = 0; i < DataGridViewLed.Rows.Count; i++)
                {
                    if (i != index)
                    {
                        DataGridViewLed.Rows[i].Selected = false;
                    }
                }
            }
\*/
        }


Die auskommentierten Zeilen verstehe ich insofern nicht, da mir nicht klar ist, ob mit DataTable hier nur eine Struktur meiner BindingSource festgelegt wird, oder ob da eine neue BindingSource erstellt wird.
Kann mir jemand helfen?

05.10.2022 - 19:28 Uhr

Ich habe es gefunden:


        private void DataGridViewFarben_RowEnter(object sender, DataGridViewCellEventArgs e)
        {
            trackBarRed.Value = (int)DataGridViewFarben[0, e.RowIndex].Value;
            trackBarGreen.Value = (int)DataGridViewFarben[1, e.RowIndex].Value;
            trackBarBlue.Value = (int)DataGridViewFarben[2, e.RowIndex].Value;
        }

RowEnter ist für meinen Anwendungsfall der richtige Eventhandler.

05.10.2022 - 18:28 Uhr

Hallo,
Ich habe bei DataGridView den SelectionMode auf FullRowSelect eingestellt. Immer wenn der User eine andere Zeile anwählt (egal wie), wird die gesamte Zeile selektiert.
Ich will dieses Event abfangen, finde aber den richtigen Eventhandler nicht. Kann mir jemand diesen nennen?

03.10.2022 - 16:07 Uhr

Danke für die Info.
Ich habe die 2. Variante gewählt. Funktioniert prächtig.

03.10.2022 - 13:04 Uhr

Hallo,
Immer, wenn der User Veränderungen im NumericUpDown macht, sollen diese Veränderungen übernommen werden. Ich will auch einen Wert in dem NumericUpDown durch eine Änderung in einer ListBox darstellen, aber die Änderung nicht übernehmen.


        private void MyNumericUpDown_ValueChanged(object sender, EventArgs e)
        {
            //wenn Werte von ListBox kommen, nicht übernehmen
            // wenn Werte von NumericUpDown-Usereingabe kommen, übernehmen 
        }

Wie geht so etwas?

01.10.2022 - 13:02 Uhr

Hallo,
ich habe schon verschiedene Artikel zu BindingSource gelesen und bin immer wieder auf Relationale Datenbanken gestoßen. Meine Anwendung ist aber sehr klein und hat ganz einfache Datenmodelle. Bei einer Liste fülle ich Spalten mittels ComboBox mit Daten aus einer anderen Liste. Aber dafür eine Datenbank einsetzen ist wie mit Kanonen auf Spatzen geschossen.
Zur Darstellung nutze ich DataGridView.
Sowohl


myDataGridView.DataSource = meineDaten

als auch


myDataGridView.DataSource = myBindingSource
myBindingSource.DataSource = meineDaten

funktionieren.
Gibt es für meinen Fall (Einfache Datenmodelle = Listen, und die eine ComboBox) noch Gründe, warum ich BindingSource benutzen sollte?

01.10.2022 - 12:27 Uhr

Habe ich gemacht - funktioniert. Auch in die Listen habe ich mich etwas eingearbeitet.
--- Mühsam ernährt sich das Eichhörnchen ---

30.09.2022 - 09:16 Uhr

Hallo allerseits,
ich möchte Daten aus einer Json-Datei in DataGridView darstellen. Dazu habe ich einen Code, der auch funktioniert. Den möchte ich aber verbessern.


            string jsonString = File.ReadAllText(@"C:\users\kstan\source\LED\testextension.txt");
            Songs = JsonSerializer.Deserialize<Song[]>(jsonString);
            string[] row = new string[5];
            for (int loop = 0; loop < Songs.Length; loop++)
            {
                row[0] = Songs[loop].VRelease;
                row[1] = Songs[loop].VTrack;
                row[2] = Songs[loop].VTitle;
                row[3] = Songs[loop].VArtist;
                row[4] = Songs[loop].VAlbum;
                songsDataGridView.Rows.Add(row);
            }

songsDataGridView.Rows.Add verlangt ein string-Array; ich habe aber ein Json-Object - daher speichere ich das um in ein string-Array.

  1. Gibt es eine Möglichkeit, das Songs-Object direkt in DataGridView einzulesen?
  2. Wie würde ein databinding aussehen? Ich kenne das nicht und komme mit der Doku nicht wirklich klar.
29.09.2022 - 19:10 Uhr

Gut zu wissen - da ich aber erst am Anfang bin und fast nichts umstellen muss, ist es für mich einfach, die Properties identisch zu machen.

29.09.2022 - 18:21 Uhr

Danke - ich hatte das einfach übersehen.
Das V ist historisch gewachsen. Das kann weg. 😉

29.09.2022 - 17:35 Uhr

Hallo allerseits,
im folgenden Programm ist das Array immer leer.


using System;
using System.IO;
using System.Text.Json;
using System.Windows.Forms;

namespace test123
{
    public partial class Form1 : Form
    {
        Song[] Songs;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            string jsonString = File.ReadAllText(@"C:\users\kstan\source\LED\testextension.txt");
            Songs = JsonSerializer.Deserialize<Song[]>(jsonString);
            for (int loop = 0; loop < Songs.Length; loop++)
            {
                MessageBox.Show(Songs[loop].VTitle);
            }

        }

        [Serializable]
        public class Song
        {
            public string VRelease { get; set; }
            public string VTrack { get; set; }
            public string VTitle { get; set; }
            public string VArtist { get; set; }
            public string VAlbum { get; set; }

            public Song(string vRelease, string vTrack, string vTitle, string vArtist, string vAlbum)
            {
                VRelease = vRelease;
                VTrack = vTrack;
                VTitle = vTitle;
                VArtist = vArtist;
                VAlbum = vAlbum;
            }

            public Song()
            {
            }
        }
    }
}


Nach dem einlesen mit File.Read steht in jsonString ein sauberer Json String. Songs.Length ist in meinem Fall 7. Trotzdem zeigt die MessageBox immer leer an.
Die Json-Datei ist


[
  {
    "ReleaseDate": "22.11.1968",
    "Track": "29",
    "Title": "Revolution 9",
    "Artist": "Beatles",
    "Album": "The Beatles White Album"
  },
  {
    "ReleaseDate": "1960",
    "Track": "6",
    "Title": "Fools Rush In",
    "Artist": "Frank Sinatra",
    "Album": "Nice N Easy"
  },
  {
    "ReleaseDate": "11.11.1971",
    "Track": "1",
    "Title": "One of These Days",
    "Artist": "Pink Floyd",
    "Album": "Meddle"
  },
  {
    "ReleaseDate": "1988",
    "Track": "7",
    "Title": "Where Is My Mind?",
    "Artist": "Pixies",
    "Album": "Surfer Rosa"
  },
  {
    "ReleaseDate": "5.1981",
    "Track": "9",
    "Title": "Can't Find My Mind",
    "Artist": "Cramps",
    "Album": "Psychedelic Jungle"
  },
  {
    "ReleaseDate": "10.6.2003",
    "Track": "13",
    "Title": "Scatterbrain. (As Dead As Leaves.)",
    "Artist": "Radiohead",
    "Album": "Hail to the Thief"
  },
  {
    "ReleaseDate": "30.6.1992",
    "Track": "3",
    "Title": "Dress",
    "Artist": "P J Harvey",
    "Album": "Dry"
  }
]

Der Debugger zeigt mit auch, dass die Daten immer Null sind. Warum?
Was ist da falsch?

25.09.2022 - 19:45 Uhr

Hallo allerseits,

ich möchte die Instanz einre ListView-Klasse in einem Formular darstellen.
Ich dachte, das geht so:


    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            ListView listView2 = new ListView();
        }
    }


Im Formular wird aber nichts dargestellt. Muss ich das ListView noch an das Form anbinden?

25.09.2022 - 19:07 Uhr

Gut - da schau ich mal nach

23.09.2022 - 19:50 Uhr

Ich merke, dass es bei mir mit der Objektorientierung noch ziemlich hapert.
Jetzt funktioniert es jedenfalls und für heute reicht es auch 😉

23.09.2022 - 19:30 Uhr

Ich versuche, jetzt Schritt für Schritt deinen Vorschlägen zu folgen.

Annahme, dass Farbe Deine Datenklasse ist


    [Serializable]
    public class Farbe
    {
        public byte FarbeNr { get; set; }
        public byte FarbeRot { get; set; }
        public byte FarbeGruen { get; set; }
        public byte FarbeBlau { get; set; }
        public string FarbeBeschreibung { get; set; }

        public Farbe(byte farbeNr, byte farbeRot, byte farbeGruen, byte farbeBlau, string farbeBeschreibung)
        {
            FarbeNr = farbeNr;
            FarbeRot = farbeRot;
            FarbeGruen = farbeGruen;
            FarbeBlau = farbeBlau;
            FarbeBeschreibung = farbeBeschreibung;
        }
    }


  • Farben lesen
  • Farbe für Farbe in die ListView eintragen

        Farbe[] Farben;
        private void ButtonRGBLesen_Click(object sender, EventArgs e)
        {
            if (File.Exists(TextBoxPath.Text + TextBoxRGB.Text))
            {
                string jsonString = File.ReadAllText(TextBoxPath.Text + TextBoxRGB.Text);
                Farben = JsonSerializer.Deserialize<Farbe[]>(jsonString);
                for (int loop = 0; loop < Farben.Length; loop++)
                {
                    ListViewItem FarbeNr = ListViewRGB.Items.Add(Convert.ToString(Farben[loop].FarbeNr));
                    FarbeNr.SubItems.Add(Convert.ToString(Farben[loop].FarbeRot));
                    FarbeNr.SubItems.Add(Convert.ToString(Farben[loop].FarbeGruen));
                    FarbeNr.SubItems.Add(Convert.ToString(Farben[loop].FarbeBlau));
                    FarbeNr.SubItems.Add(Farben[loop].FarbeBeschreibung);
                }
            }
            else
            {
                MessageBox.Show(TextBoxPath.Text + TextBoxRGB.Text + " nicht gefunden");
            }
        }


  • ListView Elemente nehmen, durch Items.Count weißt Du wie viele Elemente in der Liste sind und kannst mit dieser Info das Array initialisieren

Im Eventhandler mache ich dann folgendes:


           Farbe[] Farben = new Farbe[ListViewRGB.Items.Count];

Ich meine, dass ich dadurch ein lokales Array mit einer festen Größe definiert habe.
Und dann habe ich ein Problem:

  • Jeden Eintrag in Farbe übertragen

Wie kann ich einen Eintrag der in die Klasse Farbe übertragen? Wenn ich


Farben[loop].FarbeNr = Convert.ToByte(ListViewRGB.Items[loop].Text);

versuche, bekomme ich die Exception
System.NullReferenceException: "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."
Ich dachte, Farben sei die Instanz?

23.09.2022 - 17:24 Uhr

Ja, alles ok und akzeptiert. Aber ich bin damit leider nicht weiter.
Nochmal: ich habe ein ListView, in das ich (wie auch immer) 4 Farben eingetragen habe mit jeweils Nr, R-Wert, G-Wert, B-Wert, Beschreibung. Diese Daten habe (wie auch immer) als Json in eine Datei geschrieben. Nun fülle ich eine 5. Farbe in mein ListView und will alles nochmal als Json in der Datei haben.
Was muss ich tun? Wie muss mein Konzept für die Datenspeicherung aussehen?

23.09.2022 - 16:38 Uhr

Und ich dachte, dass hinter dem UI-Element ListView eine solche Liste steckt, die man nur richtig ansprechen muss.
Also muss ich jetzt statt meines Arrays eine Liste erzeugen, und die Daten vom UI-Element dort speichern.

23.09.2022 - 16:28 Uhr

Ich hatte es so gemacht, wie du gesagt hast, aber:
Mehrdimensionale Arrays können während Runtime nicht vergrößert werden.


                string jsonString = File.ReadAllText(TextBoxPath.Text + TextBoxRGB.Text);
                Farben = JsonSerializer.Deserialize<Farbe[]>(jsonString);
                for (int loop = 0; loop < Farben.Length; loop++)
                {
                    ListViewItem FarbeNr = ListViewRGB.Items.Add(Convert.ToString(Farben[loop].FarbeNr));
                    FarbeNr.SubItems.Add(Convert.ToString(Farben[loop].FarbeRot));
                    FarbeNr.SubItems.Add(Convert.ToString(Farben[loop].FarbeGruen));
                    FarbeNr.SubItems.Add(Convert.ToString(Farben[loop].FarbeBlau));
                    FarbeNr.SubItems.Add(Farben[loop].FarbeBeschreibung);
                }


Wenn der User eine neue Zeile im ListView erzeugt (also z.B. eine neue Farbe gelb einfügt), kann ich das nicht mehr in Farben kopieren, bzw. Farben nicht mehr erweitern. Also brauche ich etwas anderes. Letztendlich stellt sich die Frage, wie ich dieses User-Verhalten abbilden kann?

23.09.2022 - 15:40 Uhr

Aber es muss doch eine Datenklasse hinter ListView stecken - ich denke, dass es eine List ist. Aber wie hießt die und wie greife ich darauf zu?

23.09.2022 - 12:30 Uhr

Hallo allerseits,

ich möchte ein ListView deserialisieren und auch wieder serialisieren. Bisher fällt mir nichts anderes ein, als die Items und Subitems in einer Laufschleife zu durchlaufen und die Deserialisierung nach Json durch eigenen Code durchzuführen. Es gibt die Methode ListViewItem.Deserialize(SerializationInfo, StreamingContext), aber damit komme ich irgendwie nicht klar.
Ein passendes Beispiel habe ich auch nicht gefunden.
Kann mir jemand helfen?

22.09.2022 - 11:16 Uhr

Danke, das war's schon. Hätte ich eigentlich selbst drauf kommen müssen...

22.09.2022 - 10:35 Uhr

Hallo allerseits,
ich glaube, ich verstehe die Basics nicht. 🙁


            if (File.Exists(Globals.DateiPfad + "Ledsteuerung_Settings.txt"))
            {
                string jsonString = File.ReadAllText(Globals.DateiPfad + "Ledsteuerung_Settings.txt");
                Presetting[] Presettings = JsonSerializer.Deserialize<Presetting[]>(jsonString);
                ListBoxProfil.Items.Clear();
                for (int loop = 0; loop < Presettings.Length; loop++)
                {
                    ListBoxProfil.Items.Add(Presettings[loop].ProfilName);
                    if (Presettings[loop].LastOne == 1)
                    {
                        TextBoxPath.Text = Presettings[loop].Pfad;
                        TextBoxRGB.Text = Presettings[loop].RGBDatei;
                        TextBoxEvent.Text = Presettings[loop].EventDatei;
                        TextBoxTiming.Text = Presettings[loop].TimingDatei;
                        UpDownMaxRGB.Value = Presettings[loop].RGBMaxHell;
                        UpDownAnzLed.Value = Presettings[loop].AnzLed;
                        UpDownAnzRelais.Value = Presettings[loop].AnzRelais;
                        UpDownTimeLapse.Value = Presettings[loop].Zeitraffer;
                        ListBoxProfil.SelectedIndex = loop;
                    }
                }
                MessageBox.Show("in if: " + Presettings[0].RGBDatei);

            }
            MessageBox.Show(Presettings[0].RGBDatei);


(um Globals und Pfadkombination kümmere ich mich später)
Presettings[0] wird duch den Deserialisierer gefüllt. In der if-Anweisung funktioniert die MessageBox. Sobald ich aus dem if raus bin, ist Presetting = null.
Das ist sicherlich richtig, aber ich verstehe das nicht.
Hilfe!
Halt, stop - ich hab's: wenn die if-Bedingung nicht erfüllt ist, muss Presettings = null sein, da ja nix gefüllt wird.

Jetzt habe ich einen else-Zweig erstellt, aber trotzdem ist Presettings = null:


            else
            {
                Presettings = new Presetting[]
                 {
                    new Presetting(@"C:\users\kstan\source\LED\", "rgbDummy.txt", "eventDummy.txt", "timingDummy.txt", 255, 40, 8, 60, "DummyProfil", 1)
                 };
            }
            MessageBox.Show(Presettings[0].RGBDatei);


21.09.2022 - 17:53 Uhr

Hallo allerseits,
Ich habe eine Json Deserialisierung


string jsonString = File.ReadAllText(Globals.DateiPfad + "Ledsteuerung_Settings.txt");
Presetting[] Presettings = JsonSerializer.Deserialize<Presetting[]>(jsonString);


Der Json-String scheint sauber zu sein:


[
  {
    "SetPfad": "C:\\users\\kstan\\source\\LED\\",
    "SetRGBDatei": "rgb.txt",
    "SetEventDatei": "xevent.txt",
    "SetTimingDatei": "timing.txt",
    "SetRGBMaxHell": 255,
    "SetAnzLed": 40,
    "SetAnzRelais": 8,
    "SetZeitraffer": 60,
    "SetProfilName": "TestProfil",
    "SetLastOne": 1
  }
]

Die Presetting-Klasse habe ich mehrfach überprüft, aber bisher nichts auffälliges gefunden:


    [Serializable]
    public class Presetting
    {
        private string Pfad;
        private string RGBDatei;
        private string EventDatei;
        private string TimingDatei;
        private byte RGBMaxHell;
        private byte AnzLed;
        private byte AnzRelais;
        private int Zeitraffer;
        private string ProfilName;
        private byte LastOne;

        public Presetting(string pfad, string rgbDatei, string eventdatei, string timingdatei, 
            byte rgbMaxHell, byte anzLed, byte anzRelais, int zeitraffer, string profilName, byte lastOne)
        {
            Pfad = pfad;
            RGBDatei = rgbDatei;
            EventDatei = eventdatei;
            TimingDatei = timingdatei;
            RGBMaxHell = rgbMaxHell;
            AnzLed = anzLed;
            AnzRelais = anzRelais;
            Zeitraffer = zeitraffer;
            ProfilName = profilName;
            LastOne = lastOne;
        }

        public string SetPfad
        {
            get { return Pfad; }
            set { Pfad = value; }
        }
        public string SetRGBDatei
        {
            get { return RGBDatei; }
            set { RGBDatei = value; }
        }
        public string SetEventDatei
        {
            get { return EventDatei; }
            set { EventDatei = value; }
        }
        public string SetTimingDatei
        {
            get { return TimingDatei; }
            set { TimingDatei = value; }
        }
        public byte SetRGBMaxHell
        {
            get { return RGBMaxHell; }
            set { RGBMaxHell = value; }
        }
        public byte SetAnzLed
        {
            get { return AnzLed; }
            set { AnzLed = value; }
        }
        public byte SetAnzRelais
        {
            get { return AnzRelais; }
            set { AnzRelais = value; }
        }
        public int SetZeitraffer
        {
            get { return Zeitraffer; }
            set { Zeitraffer = value; }
        }
        public string SetProfilName
        {
            get { return ProfilName; }
            set { ProfilName = value; }
        }
        public byte SetLastOne
        {
            get { return LastOne; }
            set { LastOne = value; }
        }
    }


Die Instanziierung scheint auch ok:


        Presetting[] Presettings;


Visual Studio schlägt mir vor


string jsonString = File.ReadAllText(Globals.DateiPfad + "Ledsteuerung_Settings.txt");
_ = JsonSerializer.Deserialize<Presetting[]>(jsonString);

Ich kann damit nichts anfangen, aber vielleicht ist das ein Hinweis auf einen anderen Fehler.
Kann mir jemand helfen oder zumindest einen Tipp zur weiteren Fehlersuche geben?

20.09.2022 - 13:15 Uhr

Ich habe jetzt numericUpDown gewählt. Damit ist das Problem nicht existent und es ist auch einfacher zu handhaben.

19.09.2022 - 17:45 Uhr

So, es funktioniert mit Json. Hier der Code mit ein paar Testdaten.


       private void ButtonRGBLesen_Click(object sender, EventArgs e)
        {
            string jsonString = File.ReadAllText(Globals.fileNameRGB);
            Farbe[] Farben = JsonSerializer.Deserialize<Farbe[]>(jsonString);
            MessageBox.Show(Globals.fileNameRGB + " gelesen");

            MessageBox.Show(Farben[0].Beschreibung);
            MessageBox.Show(Farben[1].Beschreibung);
            MessageBox.Show(Farben[2].Beschreibung);
            MessageBox.Show(Farben[3].Beschreibung);
        }

        private void ButtonRGBSpeichern_Click(object sender, EventArgs e)
        {
            Farben = new Farbe[]
            {
                new Farbe (0, 255, 255, 255, "weiß"),
                new Farbe (1, 255, 0, 0, "rot"),
                new Farbe (2, 0, 255, 0, "grün"),
                new Farbe (3, 0, 0, 255, "blau")
            };
            string jsonString = JsonSerializer.Serialize(Farben);
            File.WriteAllText(Globals.fileNameRGB, jsonString);
            MessageBox.Show("Farben in " + Globals.fileNameRGB + " gespeichert");
        }


Ist das so ok? Oder habe ich wichtige Dinge nicht berücksichtigt?

19.09.2022 - 17:04 Uhr

Jetzt probiere ich Json und laufe prompt auf einen Fehler:


using System.Text.Json;

Json ist im Namespace von System.Text nicht vorhanden. Wie muss ich denn das vereinbaren?

19.09.2022 - 16:01 Uhr

ok, ich werde den BinaryFormatter nicht benutzen. Aber was ist dann die nächste (naheliegende) Variante? Was wird von Euch empfohlen?

19.09.2022 - 15:30 Uhr

Das habe ich gelesen. Meine Anwendung ist aber für den Privatgebrauch und beinhaltet zudem keine sensible Daten. Daher denke ich, dass BinaryFormatter für meine Anwendung ok ist.

19.09.2022 - 14:57 Uhr

Danke für den Hinweis. Ich habe das jetzt mit BinaryFormatter gelöst.

17.09.2022 - 10:44 Uhr

Hallo allerseits,

gibt es in C# etwas, um Klassen in eine Datei zu schreiben? Ich habe eine Klasse mit Daten (Strings, Bytes, Integers schön gemischt) und möchte diese speichern und dann auch wieder lesen. Irgendwie habe ich bisher noch nichts passendes gefunden.
Kann mir jemand helfen?

16.09.2022 - 17:47 Uhr

numericUpDown war mir wohl bekannt, aber ich wollte die Auf- und Ab-Pfeile nicht.
Andererseits ist es besser, eine einfache (= NumericUpDown) Lösung zu nehmen.

16.09.2022 - 14:32 Uhr

Hallo allerseits,
ich brauche eine Textbox, die ausschließlich Zahlen akzeptiert. Dazu habe ich mal rumgegoogled und mehr oder weniger komplizierte Lösungen gefunden. Letztendlich habe ich aber folgendes gemacht:


        private void TextBoxMaxLED_TextChanged(object sender, EventArgs e)
        {
            try
            {
                Globals.AnzahlLed = Convert.ToByte(TextBoxMaxLED.Text);
            }
            catch
            {
                TextBoxMaxLED.Text = "1";
                Globals.AnzahlLed = 1;
            }
        }


Dabei ist in meinem Fall Globals.AnzahlLed als byte definiert.
Wenn nun die Zuweisung im Event-Handler auf eine Exception läuft (bei byte wäre das alle Zeichen, die nicht Zahl sind, sowie Zahlen kleiner 0 oder größer 255) setze ich meine Textbox auf den Wert 1 (könnte auch 0 oder sonst etwas setzen). Ich denke, das ist eine einfache Lösung.
Was meint ihr? Gibt es bei meiner Lösung Dinge, die ich nicht berücksichtigt habe? Kann da etwas schief gehen?

16.09.2022 - 09:03 Uhr

Ziel ist eine Anwendung zur Programmierung einer Beleuchtung für eine Modelleisenbahn. Die Anwendung hat eine Form mit 4 Registerkarten. Auf einer werden die Randbedingungen behandelt; die anderen beinhalten Farben, Ereignisse und Zeitpunkte. Eine Farbe kann bei mehreren Ereignissen auftreten, mehrere Ereignisse können zum gleichen Zeitpunkt auftreten. Die Registerkarten sind ähnlich aufgebaut: Zentrales Element ist jeweils ein ListView zur Darstellung und Änderung der Daten. Es sind jeweils Buttons vorhanden Daten lesen, Daten speichern, Daten hinzufügen, Daten löschen. Die Daten sind aber jeweils unterschiedlich strukturiert.
Wenn ich die UI-Elemente alle in die Form packe, dann müssten ja die Event-Händler auch dort sein. Daten speichern und lesen ist leider immer unterschiedlich, so dass ich dort auch keine Zusammenfassung sehe.
Hast du eine Idee, die mir weiter hilft?

15.09.2022 - 18:23 Uhr

Hallo allerseits,
ich möchte einen Button aus einer Form ansprechen. Aktuell geschieht das so:
in der Form rufe ich eine Instanz einer Klasse auf:


    public partial class LEDControl : Form
    {
        ClassRGB DataRGB;

        public LEDControl()
        {
            InitializeComponent();
            DataRGB = new ClassRGB(ButtonRGBLesen);
       }


In dieser Klasse ist dann der Event-Handler:


    internal class ClassRGB
    {
        private Button ButtonLesenRGB;

        public ClassRGB(object _ButtonLesenRGB)
        {
            ButtonLesenRGB = (Button)_ButtonLesenRGB;

        }

        private void ButtonLesenRGB_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Button geklickt");

        }


Das funktioniert auch richtig. Ich möchte nun nicht alle Teile der Form in der Aufruf der Klasse (Instanziierung) bringen. Gibt es andere Möglichkeiten, den Button anzusprechen?

07.09.2022 - 14:20 Uhr

Es funktioniert jetzt und ist nicht mehr abhängig von der Position der ListView. Allerdings muss ich immer noch eine Positions-Korrektur machen.


           _tbEdit.Top = _lvSubItemEdit.Bounds.Top + 2;
           _tbEdit.Left = _lvSubItemEdit.Bounds.Left + 6;


Die könnte noch von irgendwelchen Paddings und Margins herkommen.

Danke für deine Hilfe!

07.09.2022 - 13:05 Uhr

Ich denke, dass ich _tbEdit an ListViewRGB angehängt habe.


ListViewRGB.Controls.Add(_tbEdit);

ListViewRGB ist in einer GroupBox und es gibt noch ein Label mit der Überschrift oberhalb von ListViewRGB.

Habe jetzt gerade festgestellt: wenn ich ListViewRGB innerhalb der GroupBox verschiebe, ändert sich auch der Offset...

07.09.2022 - 12:32 Uhr

Hallo allerseits,
ich möchte in einem ListView einzelne Zellen editieren. Dazu lege ich eine TextBox über die entsprechende Zelle, editiere diese und kopiere das Ergebnis in das SubItem. Mit einem Code von Codezentrale "Editieren von ListView Subitems mittels TextBox" funktioniert das auch prinzipiell. Allerdings erscheint die TextBox nicht über der zu editierenden Zelle, sondern 45 Pixel zu tief und 2 Pixel zu weit rechts. Hier ist die entsprechende Stelle:


        // Event des ListViews
        // zum Merken des zuletzt angeklickten ListViewItems
        private void ListViewRGB_MouseUp(object sender, MouseEventArgs e)
        {
            ListViewHitTestInfo htInfo = ListViewRGB.HitTest(e.X, e.Y);
            if (htInfo != null)
            {
                if (htInfo.Item != null && htInfo.SubItem != null)
                {
                    _lvSubItemEdit = htInfo.SubItem;
                }
            }
        }

        // bei Doppelklick auf ein SubItem die Textbox anzeigen
        private void ListViewRGB_DoubleClick(object sender, EventArgs e)
        {
            // Größe anpassen
            _tbEdit.Top = ListViewRGB.Top - 45 + _lvSubItemEdit.Bounds.Top + 2;
            _tbEdit.Left = ListViewRGB.Left -2 + _lvSubItemEdit.Bounds.Left + 2;
            _tbEdit.Width = _lvSubItemEdit.Bounds.Width;
            _tbEdit.Height = _lvSubItemEdit.Bounds.Height;
            // Inhalt übergeben
            _tbEdit.Text = _lvSubItemEdit.Text;
            // anzeigen
            _tbEdit.Visible = true;
            _tbEdit.BringToFront();
            _tbEdit.Focus();
        }


ListViewRGB ist meine Listbox. _tbEdit ist die Textbox.
Ich habe schon -45 und -2 als Korrektur eingefügt, aber das kann es ja nicht wirklich sein.
Wo ist mein Fehler? Hat jemand eine Idee?

03.09.2022 - 11:15 Uhr

Vielen Dank für deine Empfehlung.
Ich denke, dass ich eine Binärdatei brauche, da die Daten später in einen Arduino transferiert werden, wo sie dann auf einem Farbdisplay dargestellt werden. Letztendlich werden die Farben dann in einer Modelleisenbahnanlage zur Beleuchtung genutzt. Die Anzahl der unterschiedlichen Farben hält sich dann auch in Grenzen (schätze mal max. 20).
Da ich die Daten im Arduino als Bytes brauche, muss die Umwandlung dorthin irgendwo passieren: entweder direkt als Bytes speichern, oder anders und dann beim Transfer zum Arduino. Für das direkte speichern spricht die Tatsache, dass ich die Daten sogar auf ein MicroSD speichern kann und dieses dann im Arduino direkt lesen kann.
Mein struct würde dann so aussehen:


struct Farben
{
byte Rot
byte Gruen
byte Blau
char[20] Beschreibung
}


Die Umwandlung der struct-Daten in zu speichernde Bytes (nennt man das Serialisierung?) wäre noch zu klären. Gibt es da Empfehlungen?

Lg Karl

02.09.2022 - 18:36 Uhr

Hallo allerseits,
ich bin Anfänger. Ich möchte Daten aus einer Datei lesen, diese in einer Tabelle darstellen, modifizieren (ändern, hinzufügen, löschen) und wieder abspeichern. Jetzt suche ich eine angemessene Art dies zu tun. Hier geht es jetzt zuerst nur einmal um die Darstellung der Daten.
Ich habe mir vorgestellt, dass ich Datensätze in der Form von einem struct darstelle.


struct Farben
{
byte Rot
byte Gruen
byte Blau
string[20] Beschreibung // soll maximal 20 char lang sein
}

In der Datei sollen die Daten Byteweise abgespeichert sein.

  1. Ist struct der geeignete Ansatz?
  2. Wie wandele ich die Serie von Bytes aus der Datei in ein Array von Farben um?
    z.B. als Methode 1. Byte = Farbe[0].Rot, 2. Byte = Farbe[0].Gruen, 3. Byte = Farbe[0].Blau, 4. - 24. Byte = Farbe[0].Beschreibung, dann weiter mit Farbe[1] usw.

Wie soll ich vorgehen? Was wird empfohlen?
Mir geht es zuerst einmal um das Konzept. Die eine oder andere Codezeile zur Erklärung wäre auch nicht schlecht.

Lg Karl

16.08.2022 - 13:59 Uhr

Genau das war es. Habe ButtonNeuSchreiben gelöscht - damit ist die Methode in Form1 verschwunden.

Viele Dank!

16.08.2022 - 11:48 Uhr

Hallo allerseits,
ich benutze Visual Studio 2022, 17.2.6 und bastele etwas mit C# und .NET 4.8

Ich habe ein Formular erstellt und alles darin in eine eigene Klasse gestellt. Nun erwarte ich, dass im Code von Form1 nur noch der Aufruf der Klasse ist, aber ich sehe noch 2 Methoden:


using System;
using System.Windows.Forms;

namespace DatenSpeichern
{
    public partial class FormEinAusgabe : Form
    {
        SpeichernDatei Speichern1;

        public FormEinAusgabe()
        {
            InitializeComponent();
            Speichern1 = new SpeichernDatei(TextBoxEingabe, ButtonNeuSchreiben, ButtonAnhaengen, TextBoxAusgabe, ButtonDateiLesen, ButtonDateiLoeschen);
        }

        private void EinAusgabe_Enter(object sender, EventArgs e)
        {
        }

        private void ButtonNeuSchreiben_Click(object sender, EventArgs e)
        {
        }
    }
}

Die Methode EinAusgabe_Enter kann ich verstehen: sie wurde erzeugt, als ich im grafischen Entwurf auf die GroupBox doppelt geklickt habe.
Die Methode ButtonNeuSchreiben_Click habe ich auch per Doppelklick hier erzeugt; sie sollte hier nicht sein, da sie bereits in der anderen Klasse ist. Wenn ich sie lösche, erhalte ich einen Fehler, da noch ein Verweis auf etwas in Form1.Designer existiert. Den Code im Designer sollte man aber besser nicht ändern, da er automatisch erstellt wird.

Gibt es eine Möglichkeit, Form1 zu bereinigen und damit die Methode samt ihrer Verweise dort zu löschen?

Vielleicht kann mir jemand damit helfen?

Viele Grüße

16.08.2022 - 10:53 Uhr

Es funktioniert - vielen Dank für die Hilfe.
So habe ich es jetzt gemacht:
Vereinbart wurde der Timer mit


private Timer T1;

Der Konstruktor beinhaltet jetzt


T1 = new System.Windows.Forms.Timer();
T1.Tick += new EventHandler(T1_Tick);
T1.Interval = 2000;

und der Event-Handler ist


        public void T1_Tick(object sender, EventArgs e)
        {
            T1.Stop();
            ButtonNeuSchreiben.BackColor = SystemColors.Control;
        }

Nochmals Danke!

15.08.2022 - 19:41 Uhr

Hallo allerseits,
ich bin blutiger Anfänger, habe es aber schon geschafft, ein Formular zu erzeugen. Dort sind einige Testboxen und einige Buttons. Wenn ich nun einen Button ButtonNeuSchreiben betätige, soll dieser für 2 Sekunden grün sein und dann wieder normal. Mein Projekt läuft mit .NET 4.8.


        public void ButtonNeuSchreiben_Click(object sender, EventArgs e)
        {
            if (TextBoxEingabe.Text != "")
            {
                File.WriteAllText(dateiName, TextBoxEingabe.Text);
                T1.Start();
                ButtonNeuSchreiben.BackColor = Color.FromArgb(196, 255, 196);
            } else
            {
                ButtonNeuSchreiben.BackColor = Color.FromArgb(255, 196, 196);
            }
        }

Den Timer habe ich vorher mit


private static Timer T1;

definiert und im Konstruktor mit


            T1 = new Timer();
            T1.Interval = 2000;

generiert.

Die Eventbehandlung lautet


        public static void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
        {
            T1.Stop();
            ButtonNeuSchreiben.BackColor = SystemColors.Control;
        }

Irgendwie funktioniert das aber nicht. Ich habe die Meldung, dass ButtonNeuSchreiben nicht static ist. Warum muss das static sein? Warum ist der Timer static? Ich habe dann mal den Button static vereinbart. Dann habe ich keine Fehlermeldung, funktioniert aber trotzdem nicht.

Vielleicht kann mir jemand helfen?

Viele Grüße
Karl