Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Daten aus DataGrid per RestAPI speichern
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

Daten aus DataGrid per RestAPI speichern

beantworten | zitieren | melden

Verwendetes Datenbanksystem: MariaDB
Verwendete API: RestSharp

Hallo zusammen,
erneut habe ich eine Frage.
Aktuell lade ich einige Daten per RestApi in ein DataGrid. Die Anzeige, der darin enthaltenen Daten funktioniert soweit ganz gut.
Jetzt möchte ich die einzelnen Zeilen abändern und automatisch in der Datenbank speichern können.
Das speichern sollte ebenfalls mittels RestSharp funktionieren.

Nur, wie gehe ich da am besten vor? Wie bekomme ich die Inhalt der einzelnen Zeilen eines DataGrid.
Wie speichere ich den geänderten Wert automatisch? Oder geht es nur per Button?

Hier mein Code:

<DataGrid ItemsSource="{Binding LDKompetenzen}" AutoGenerateColumns="False" CanUserDeleteRows="False" CanUserAddRows="False" CanUserSortColumns="True" FontSize="12" Height="Auto" BorderThickness="0">
                <DataGrid.Resources>
                    <Style BasedOn="{StaticResource {x:Type DataGridColumnHeader}}" TargetType="{x:Type DataGridColumnHeader}" >
                        <Setter Property="Background" Value="LightGray" />
                        <Setter Property="Foreground" Value="Black" />
                        <Setter Property="BorderBrush" Value="Black"/>
                        <Setter Property="BorderThickness" Value="1 1 1 1"/>
                        <Setter Property="Margin" Value="-1,-1,0,0" />
                        <Setter Property="Height" Value="28" />
                        <Setter Property="Width" Value="auto"/>
                        <Setter Property="HorizontalContentAlignment" Value="Center"/>
                        <Setter Property="FontWeight" Value="SemiBold"/>
                        <Setter Property="FontStyle" Value="Italic"/>
                        <Setter Property="FontSize" Value="15"/>
                        <Setter Property="Padding" Value="15,0,15,0"/>
                    </Style>
                </DataGrid.Resources>
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Kompetenz" Binding="{Binding Kompetenz}" IsReadOnly="True">
                        <DataGridTextColumn.ElementStyle>
                            <Style TargetType="{x:Type TextBlock}">
                                <Setter Property="TextBlock.Background" Value="{Binding Background}" />
                                <Setter Property="HorizontalAlignment" Value="Stretch"/>
                                <Setter Property="VerticalAlignment" Value="Stretch"/>
                                <Setter Property="TextAlignment" Value="Center"/>
                                <Setter Property="Padding" Value="0,20,0,0"/>
                            </Style>
                        </DataGridTextColumn.ElementStyle>
                    </DataGridTextColumn>
                    <DataGridTemplateColumn Header="Farben" IsReadOnly="True">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
                                    <Button Content="" Background="White" Margin="2" Padding="5,3,5,3"></Button>
                                    <Button Content="" Background="Yellow" Margin="2" Padding="5,3,5,3"></Button>
                                    <Button Content="" Background="LightGreen" Margin="2" Padding="5,3,5,3"></Button>
                                </StackPanel>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTextColumn Header="Stufe" Binding="{Binding Stufe, UpdateSourceTrigger=LostFocus, Mode=TwoWay}" >
                        <DataGridTextColumn.ElementStyle>
                            <Style TargetType="{x:Type TextBlock}">
                                <Setter Property="HorizontalAlignment" Value="Center"/>
                                <Setter Property="VerticalAlignment" Value="Center"/>
                            </Style>
                        </DataGridTextColumn.ElementStyle>
                    </DataGridTextColumn>
                    <DataGridTextColumn Header="Niveau" Binding="{Binding Niveau, UpdateSourceTrigger=LostFocus, Mode=TwoWay}">
                        <DataGridTextColumn.ElementStyle>
                            <Style TargetType="{x:Type TextBlock}">
                                <Setter Property="HorizontalAlignment" Value="Center"/>
                                <Setter Property="VerticalAlignment" Value="Center"/>
                            </Style>
                        </DataGridTextColumn.ElementStyle>
                    </DataGridTextColumn>
                    <DataGridTextColumn Header="Ergebnis" Binding="{Binding Ergebnis, UpdateSourceTrigger=LostFocus, Mode=TwoWay}">
                        <DataGridTextColumn.ElementStyle>
                            <Style TargetType="{x:Type TextBlock}">
                                <Setter Property="HorizontalAlignment" Value="Center"/>
                                <Setter Property="VerticalAlignment" Value="Center"/>
                            </Style>
                        </DataGridTextColumn.ElementStyle>
                    </DataGridTextColumn>
                    <DataGridTextColumn Header="Note" Binding="{Binding Note, UpdateSourceTrigger=LostFocus, Mode=TwoWay}">
                        <DataGridTextColumn.ElementStyle>
                            <Style TargetType="{x:Type TextBlock}">
                                <Setter Property="HorizontalAlignment" Value="Center"/>
                                <Setter Property="VerticalAlignment" Value="Center"/>
                            </Style>
                        </DataGridTextColumn.ElementStyle>
                    </DataGridTextColumn>
                    <DataGridTemplateColumn Header="Datum">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <DatePicker SelectedDate="{Binding Datum, UpdateSourceTrigger=LostFocus, Mode=TwoWay}" BorderThickness="0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTextColumn Header="Kürzel" Binding="{Binding Kuerzel, UpdateSourceTrigger=LostFocus, Mode=TwoWay}">
                        <DataGridTextColumn.ElementStyle>
                            <Style TargetType="{x:Type TextBlock}">
                                <Setter Property="HorizontalAlignment" Value="Center"/>
                                <Setter Property="VerticalAlignment" Value="Center"/>
                            </Style>
                        </DataGridTextColumn.ElementStyle>
                    </DataGridTextColumn>
                </DataGrid.Columns>
            </DataGrid>


Ich bin für einige Gedankenansetze von euch sehr Dankbar!

Grüße
Sascha
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Sascha87 am .
Attachments
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 2.032
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

Laut Doku, hat das DataGrid ein RowEditEnding Event, was du vermutlich abonieren müsstest.
In der Doku dürftest du auch einen Ansatz dafür finden.

Doku:
DataGrid.RowEditEnding Ereignis (System.Windows.Controls)

T-Virus
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.432

beantworten | zitieren | melden

Du hast doch per Binding die Eigenschaft LDKompetenzen als ItemsSource angegeben.
Solange du nach MVVM vorgegangen bist und dessen Klasse INotifyPropertyChanged implementiert hast, werden automatisch alle Änderungen der DataGrid-Werte zurück geschrieben.
Du brauchst also nur dieses LDKompetenzen-Objekt mittels RestSharp serialisieren.
Welchen genauen Datentyp hat denn diese Eigenschaft?

Und was genau meinst du mit "automatisch"? Sollen nach jeder Änderung sofort alle Daten zurückgeschrieben werden?
Oder möchtest du, daß nur die geänderten Daten ermittelt werden? Dann schau mal in How do you handle data grid cell changes with MVVM? sowie Apply changes to Model when a row of DataGrid is changed using MVVM.

@T-Virus: Dein Ansatz ist aber nicht MVVM-konform.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16.030

beantworten | zitieren | melden

Zitat
Wie speichere ich den geänderten Wert automatisch? Oder geht es nur per Button?
Es empfiehlt sich a) sowas nicht automatisch zu speichern und b) auch einen Lock-Mechanismus einzubauen.
Die Erfahrung zeigt, dass sich ansonsten die Anwender gegenseitig Zeug überschreiben ohne, dass es bemerkt wird.

Optimistische Nebenläufigkeit - ADO.NET ist ein relativ alter Artikel, der noch auf dem DataSet beruht; erklärt aber die Prinzipien.
Im Falle von REST musst das eh selbst implementieren (was auch gut so ist).
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 2.032
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

@Th69
Hatte ich schon vermutet.
Bin leider nicht sehr aktiv mit WPF unterwegs, weshalb ich nur oberflächlich mit den Konzepten vertraut bin.

T-Virus
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.432

beantworten | zitieren | melden

Dafür gibt es extra das Interface IEditableObject (wie in meinem 2. Link erklärt).
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Vielen Dank für die Links.
Beim ersten Link: Ich nutze .NET 4,75 (Galasoft geht nur bis 4.5). Daher kann ich keine "Galasoft WPF" hinzufügen.

Link 2: Ich nutze in meiner ViewModel INotifyPropertyChanged.

Funktioniert es, wenn ich eine entsprechende Funktion in die Viewmodel schreibe mit IEditableObject?
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.432

beantworten | zitieren | melden

Das MVVM Light Toolkit sollte eigentlich auch mit .NET 4.7 funktionieren, nur mit dem aktuellen .NET 5 wohl bisher nicht: .NET Framework 4.7 to .NET 5 Migration with Galasoft MVVMLight Library.

Aber ich denke auch, daß IEditableObject der einfachere Weg ist.
Du hast doch sicherlich LDKompetenzen als ObservableCollection<X> deklariert? Dann mußt du IEditableObject für die Klasse X implementieren.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 2.032
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

@Sascha87
Was ist .NET 4,75?
Die Version ist mir neu.

Link:
Bestimmen der installierten .NET Framework-Versionen

T-Virus
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Ich weiß nicht was mich da geritten hat.....4.7.2 meine ich.
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Genau, die Klasse ist als ObservableCollection deklariert. In diese Klasse kann ich dann eine weitere Methode mit IEditableObject einfügen?
Es tut mir Leid, es ist Neuland für mich
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.432

beantworten | zitieren | melden

Hast du noch nie eine Schnittstelle implementiert (ist fast identisch zum Ableiten einer Basisklasse)?

So wie es auch in dem Link steht (nur statt RowViewModel in deine Klasse diese Schnittstelle hinzufügen sowie die 3 Methoden einfügen - wobei du dann nur EndEdit mit Code füllst).
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Also, folgendes habe ich gemacht:

ViewModel:
Die Klasse erweitert:


class LDViewModel : NotifyPropertyBase, IEditableObject

Anschließend folgendes gefüllt:


    public void EndEdit()
        {
            var client = new RestClient("https://xxxxxxxxde/");
            var request = new RestRequest("ld/LDUpdate/{name}/{kompetenzID/{ergebnis}/{stufe}/{niveau}/{note}/{datum}/{kuerzel}", Method.POST)
                .AddUrlSegment("name", Name)
                .AddUrlSegment("kompetenzID", LDCurrentKompetenz.KompetenzID)
                .AddUrlSegment("ergebnis", LDCurrentKompetenz.Ergebnis)
                .AddUrlSegment("stufe", LDCurrentKompetenz.Stufe)
                .AddUrlSegment("niveau", LDCurrentKompetenz.Niveau)
                .AddUrlSegment("note", LDCurrentKompetenz.Note)
                .AddUrlSegment("datum", LDCurrentKompetenz.Datum)
                .AddUrlSegment("kuerzel", LDCurrentKompetenz.Kuerzel)
                .AddHeader("Authorization", "Bearer " + ViewFingerPrint);

            IRestResponse restResponse = client.Execute(request);

            if (restResponse.StatusCode == HttpStatusCode.BadRequest)
            {
                MessageBox.Show("Irgendetwas stimmt mit der Verbindung nicht.");
            }
            else
            {
                MessageBox.Show("Die Leistungsdokumentation wurde erfolgreich aktualisiert.");
            }
        }

Allerdings reagiert er nicht. Woher weiß er, welches DataGrid gemeint ist?
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.432

beantworten | zitieren | melden

Das erscheint mir die falsche Klasse zu sein?!
Du mußt die Schnittstelle in der Klasse implementieren, welche eine Zeile deiner Daten entspricht (schau oben noch mal in meinen Beitrag bzgl. der Klasse X).

Wenn du doch die eigentliche Funktionalität (RestAPI) in deinem Hauptviewmodel implementieren möchtest, dann erzeuge in deiner Klasse X ein (statisches) Ereignis (s.a. [FAQ] Eigenen Event definieren / Information zu Events (Ereignis/Ereignisse)) und abonniere es von deinem Hauptviewmodel.
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Das ist meine ViewModel.
In deinem Beispiel sowie unzählige andere wurde es dort implementiert.
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.432

beantworten | zitieren | melden

Nein, in meinem Link steht explizit RowViewModel (Row = Zeile), nicht das ViewModel, in dem die ItemsSource definiert ist.

Zeige doch mal, wie du die Eigenschaft LDKompetenzen in deinem Hauptviewmodel definiert hast.

Edit: Schau auch mal in Implementing IEditableObject in model in mvvm pattern, am i breaking pattern? (als Antwort hat der Beitragsersteller 'first100' seinen Code mit der Klasse Company, welche IEditableObject implementiert, und dem ViewModel mit der Eigenschaft SearchCompanies gepostet).
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Ok, dann habe ich das falsch verstanden.

Die LDKompetenzen hole ich so in das ViewModel:


public LDKompetenzen LDKompetenzen { get; set; }

So lade ich die "Current" Version:


LDKompetenz _ldcurrentKompetenz = null;
        public LDKompetenz LDCurrentKompetenz
        {
            get { return _ldcurrentKompetenz; }
            set
            {
                if (value == null)
                    return;
                OnPropertyChanged(ref _ldcurrentKompetenz, value);
            }
        }

So lade ich die Daten in die View:


LDKompetenzen = LDKompetenzen.Load(LDCurrentFach.FachID, value.ThemaID, ViewFingerPrint, Name);
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.432

beantworten | zitieren | melden

Und was ist jetzt die Klasse LDKompetenzen (du hast doch auch von ObservableCollection<...> geschrieben)?

So wie ich deine Eigenschaft "LDCurrentKompetenz" richtig verstehe, solltest du also dann in der Klasse LDKompetenz das Interface IEditableObject implementieren.
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Das ist hier meine Klasse:



class LDKompetenzen : ObservableCollection<LDKompetenz>
    {
        private static readonly LDKompetenzen _kompetenzen = new LDKompetenzen();

        private LDKompetenzen() { }

        public static LDKompetenzen Load(string fachID, string themenID, string ViewFingerPrint, string name)
        {
            _kompetenzen.Clear();
            try
            {
                var client = new RestClient("MEINEDOMAIN");

                var request = new RestRequest("ld/kompetenzen/{fachid}/{themenid}/{SHDID}", Method.GET)
                .AddHeader("Authorization", "Bearer " + ViewFingerPrint)
                .AddUrlSegment("fachid", fachID)
                .AddUrlSegment("SHDID", name)
                .AddUrlSegment("themenid", themenID);

                IRestResponse restResponse = client.Execute(request);
                HttpStatusCode statusCode = restResponse.StatusCode;
                if ((int)statusCode != 401)
                {
                    var arr = JsonConvert.DeserializeObject<JArray>(restResponse.Content);
                    foreach (JObject obj in arr)
                    {
                        var KompetenzID = (string)obj["id"];
                        var Kompetenz = (string)obj["Kompetenz"];
                        var SHDID = (string)obj["SHDID"];
                        var Ergebnis = (string)obj["Ergebnis"];
                        var Stufe = (string)obj["Stufe"];
                        var Niveau = (string)obj["Niveau"];
                        var Note = (string)obj["Note"];
                        var Datum = (string)obj["Datum"];
                        var Kuerzel = (string)obj["Kuerzel"];
                        var background = (string)obj["background"];

                            _kompetenzen.Add(new LDKompetenz(KompetenzID, Kompetenz, SHDID, Ergebnis, Stufe, Niveau, Note, Datum, Kuerzel, background));
                    }
                }
                else
                {
                    var KompetenzID = "0";
                    var Kompetenz = "";
                    var SHDID = "";
                    var Ergebnis = "";
                    var Stufe = "";
                    var Niveau = "";
                    var Note = "";
                    var Datum = "";
                    var Kuerzel = "";
                    var background = "white";

                    _kompetenzen.Add(new LDKompetenz(KompetenzID, Kompetenz, SHDID, Ergebnis, Stufe, Niveau, Note, Datum, Kuerzel, background));
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
            return _kompetenzen;
        }
    }

Und die greift auf folgende zu:



        public LDKompetenz(string kompetenzID, string kompetenz, string shdID, string ergebnis, string stufe, string niveau, string note, string datum, string kuerzel, string background)
        {
            KompetenzID = kompetenzID;
            Kompetenz = kompetenz;
            SHDID = shdID;
            Ergebnis = ergebnis;
            Stufe = stufe;
            Niveau = niveau;
            Note = note;
            Datum = datum;
            Kuerzel = kuerzel;
            Background = background;
        }

        //Anzeige Fördermaßnahmen
        public string KompetenzID { get; set; }
        public string Kompetenz { get; set; }
        public string SHDID { get; set; }
        public string Ergebnis { get; set; }
        public string Stufe { get; set; }
        public string Niveau { get; set; }
        public string Note { get; set; }
        public string Datum { get; set; }
        public string Kuerzel { get; set; }
        public string Name { get; set; }
        public string Background { get; set; }

        public bool IsSelected { get; set; }

        public override string ToString()
        {
            return $"{Kompetenz}";
        }
    }

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Sascha87 am .
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.432

beantworten | zitieren | melden

OK, und wie ich vermutet habe, mußt du es in der Klasse LDKompetenz implementieren. Dort hast du dann Zugriff auf alle Member der aktuell geänderten Datenzeile.

PS: Deinen Namen und E-Mail solltest du besser wieder wegeditieren.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 2.032
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

Nachträglich noch der Tipp:
Wenn du Strings hardcoden musst, dann macht das über Konstanten.
Literale im Code sind eine sehr unschöne Sache und gehen auch bei einigen Umsetzungen auch in Richtung Magic Strings.

Auch wäre es besser wenn du anstelle von "" als Wert String.Empty verwendest.
Durch "" im Code erzeugst du zusätzliche Literale, was die Laufzeitumgebung zwar abfängt aber durch String.Empty wird eine statische Instanz verwendet und der Code ist auch klarer ausgedrückt.

Auch würde ich empfehlen die Deserialierung des Json umzubauen.
Was du im Grund hast, ist eine Liste von Objekten.
Du kannst hier einfach List<T> als Container verwenden und eine entsprechende Klasse anlegen, die ein einzelnes Objekt der Api abbildet.
Dadurch sparst du dir den Aufwand die Eigenschaften einzeln auslesen und die Liste selbst aufbauen zu müssen.
Kann an der Stelle der Deseralisierer übernehmen.
Spart dir unnötigen Aufwand und Zeit bei der Umsetzung

T-Virus
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Ok, das teste ich mal.

Ich benötige noch die Variabel "Name" aus der ViewModel. Das ist eine TextBox aus der View.

Dazu habe ich folgendes in der ViewModel:


        private string _name = "1";
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                if (value == "" && value == null)
                    return;
                _name = value;
                LDKompetenzen = LDKompetenzen.Load(LDCurrentFach.FachID, LDCurrentThema.ThemaID, ViewFingerPrint, Name);
                OnPropertyChanged(ref _name, value);
            }
        }

Kann ich es ganz normal mit Name {get set} in der LDKompetenz laden?
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Zitat von T-Virus
Nachträglich noch der Tipp:
Wenn du Strings hardcoden musst, dann macht das über Konstanten.
Literale im Code sind eine sehr unschöne Sache und gehen auch bei einigen Umsetzungen auch in Richtung Magic Strings.

Auch wäre es besser wenn du anstelle von "" als Wert String.Empty verwendest.
Durch "" im Code erzeugst du zusätzliche Literale, was die Laufzeitumgebung zwar abfängt aber durch String.Empty wird eine statische Instanz verwendet und der Code ist auch klarer ausgedrückt.

Auch würde ich empfehlen die Deserialierung des Json umzubauen.
Was du im Grund hast, ist eine Liste von Objekten.
Du kannst hier einfach List<T> als Container verwenden und eine entsprechende Klasse anlegen, die ein einzelnes Objekt der Api abbildet.
Dadurch sparst du dir den Aufwand die Eigenschaften einzeln auslesen und die Liste selbst aufbauen zu müssen.
Kann an der Stelle der Deseralisierer übernehmen.
Spart dir unnötigen Aufwand und Zeit bei der Umsetzung

T-Virus

Ok, danke für die Tipps! Dann werde ich mir mal anschauen wie es mit den Listen funktioniert.
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.432

beantworten | zitieren | melden

Wofür ist denn in der Klasse LDKompetenz die bisher nicht benutzte Eigenschaft Name gedacht?

Der design-technisch beste Weg wäre wirklich das Erzeugen eines Ereignisses (mit dem aktuellen LDKomptenz-Objekt als Eigenschaft), so daß die ViewModel-Klasse (bzw. weiterdelegiert an eine Datenzugriffsklasse) dann die eigentliche RestAPI-Serialisierung durchführt.

Falls du hier nur genau ein LDKompetenzen-Objekt in deinem Projekt hast, könntest du auch dort eine public static string Name-Eigenschaft anlegen, welche dann von der Load-Methode gesetzt wird: Name = name.
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Vielen vielen Dank! Mein Verständnis erweitert sich und es funktioniert fast.

Ein einziges Problem habe ich noch. Das Datum gebe ich als String weiter.

Den string ändere ich ab, damit es kein Backslash im string ist


var newdate = Datum.Replace(@"/", "-");

Allerdings lässt er die Uhrzeit. Wie bekomme ich die wohl weg?
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Sascha87 am .
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.432

beantworten | zitieren | melden

Ein Datum solltest du immer als DateTime(Offset) speichern und nur für die Ausgabe in ein bestimmtes Format als String umwandeln (Parse/ParseExact sowie ToString(format)), s.a. das aktuelle Thema c# Datum umwandeln?
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Das hatte ich ursprünglich. Leider bekomme ich beim JSon Objekten Probleme:


var arr = JsonConvert.DeserializeObject<JArray>(restResponse.Content);
                    foreach (JObject obj in arr)
                    {
                        var KompetenzID = (string)obj["id"];
                        var Kompetenz = (string)obj["Kompetenz"];
                        var SHDID = (string)obj["SHDID"];
                        var Ergebnis = (string)obj["Ergebnis"];
                        var Stufe = (string)obj["Stufe"];
                        var Niveau = (string)obj["Niveau"];
                        var Note = (string)obj["Note"];
                        DateTime Datum = (DateTime)obj["Datum"];
                        var Kuerzel = (string)obj["Kuerzel"];
                        var background = (string)obj["background"];

                        _kompetenzen.Add(new LDKompetenz(KompetenzID, Kompetenz, SHDID, Ergebnis, Stufe, Niveau, Note, Datum, Kuerzel, background, name, ViewFingerPrint));
                    }

Ich habe Tabelle 1 mit 20 Daten. In Tabelle 2 habe ich die Nutzerinformationen dazu. Nicht zu jeder Zeile aus Tabelle 1 gibt es Nutzerdaten. Daher kann es passieren, dass DateTime Datum = null ist.
Dann bekomme ich eine Fehlermeldung (siehe Bild).
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Sascha87 am .
Attachments
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.432

beantworten | zitieren | melden

Dann benutze Nullable<DateTime> (bzw. DateTime?), s.a. Nullable-Werttypen.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16.030

beantworten | zitieren | melden

Bitte keine Exceptions als Bilder anfügen. Das erschwert vieles, verwende das ERROR-Tag. Danke Dir.
Siehe auch [Hinweis] Wie poste ich richtig?

Ansonsten nimm den Hinweis von Th69 an: REST gibt eigentlich vor, dass die ISO 8601 Regel beachtet wird (machen einige leider nicht).
Siehe auch [FAQ] DateTime vs. DateTimeOffset und der Umgang mit Zeiten in .NET
Dass Du versuchst null in ein Objekt zu casten ist halt nen klassischer Fehler im Code. Musst halt vorher auf null prüfen.

Du könntest Dir as ganze manuelle Casten sparen, wenn Du zB statt dem eher angestaubten RestClient einfach Refit verwenden würdest.
Ansonsten kannst Du zumindest die meisten Fälle mit dem eingebauten Serializer abdecken:


var response = await client.PostAsync<TYPEHERE>(request);
Den Uhrzeitpattern kannst Du definieren: Serialization | RestSharp
private Nachricht | Beiträge des Benutzers
Sascha87
myCSharp.de - Member



Dabei seit:
Beiträge: 48

Themenstarter:

beantworten | zitieren | melden

Vielen lieben Dank Th69!
Soweit klappt alles.
Das Einzige, das mir aufgefallen ist, der Speichert die Daten erst in der Datenbank, wenn man alle Zellen einmal angeklickt hat.
Manche Zellen sollen zwischendurch leer bleiben. Wäre das in der Umsetzung noch möglich? Oder muss ich eher auf CellEditEnding gehen?
private Nachricht | Beiträge des Benutzers