Laden...

Forenbeiträge von ErfinderDesRades Ingesamt 5.299 Beiträge

16.03.2016 - 23:19 Uhr

ich würde das Settings-Form auch mit frm.ShowDialog() anzeigen, dann ist es ein Dialog.

Hat den Vorteil einer eindeutigen Benutzerführung.
Also wenn der Dialog geöffnet wird, ist die Anwendung automatisch solange unerreichbar, bis der User den Dialog schließt.
Zum Schließen gibts 2 Möglichkeiten: Ok oder Cancel.
Im Cancel-Fall passiert ühaupt nix, bei Ok werden die getätigten Eingaben verarbeitet, bevors weiter geht.

Dieser Pattern wird von WinForms auch sehr gut unterstützt, guggemol Video:
https://www.vb-paradise.de/index.php/Thread/88463-Instanziierung-von-Forms-und-Aufruf-von-Dialogen/?postID=773880#post773880

16.03.2016 - 23:13 Uhr

ich hab hier ein Projekt auf Platte mit einem ownerDrawn Matrix-Control.

Also man kann einstellen, wieviele Zeilen und Spalten, und der malt die dann, und macht Zahlen rein, und mit Maus kann man Zellen an-/ab-wählen.

Ist halt als Demo gedacht genau für OwnerDrawn Matrixe.

Ist allerdings vb.net - müssteste dir ggfs übersetzen.
Aber sag mir erst, ob du's ühaupt haben willst.

16.03.2016 - 03:10 Uhr

ich finde das komisch, es mit einem Behavior zu versuchen.

Für mein Geschmack wäre das zunächstmal ein Fall für eine Property der Viewmodel-Daten: IsDisplayed oder sowas.
Da muss ja auch iwie ein Konfigurations-modell bestehen, und ist wohl auch abzuspeichern, je nach Kunden, oder?

14.03.2016 - 03:42 Uhr

Die Anzeige der Header - verwendest du da Databinding?

Weil darauf kommts ja an, bei einem DataTemplate.

13.03.2016 - 13:49 Uhr

Colorierung ist eine Sache der Darstellung.
Imo macht man das am besten im CellPainting-Event. Dadurch ist egal, wo im DGV ein Datensatz steht, sondern was er beinhaltet bestimmt die Farbe.

https://www.vb-paradise.de/index.php/Thread/60305-coloriertes-datagridview/#post470886

13.03.2016 - 13:40 Uhr

kannst du ühaupt iwas anzeigen in diesem DataTemplate?

Bzw. gibts beim Testlauf im Outputfenster niccht ellenlange Meldungen zu Binding-Mismatches?

05.03.2016 - 20:07 Uhr

Hi!

Ich bin noch bisserl am gucken, ich muss auch bischen umbauen, weil ich nur VS2013 hab.

Was mir auffält ist ein bischen glaub kritischer Umgang mit null-Werten - Beispiel:


      static void AttachCallback(DependencyObject o, DependencyPropertyChangedEventArgs e)        {
            var eventName = e.NewValue as string;
            if (string.IsNullOrEmpty(eventName)) return;
            if (AttachedEvents == null || string.IsNullOrEmpty(AttachedEvents[eventName])) return;
            var eventInfo = o?.GetType().GetEvent(eventName);
            var eventType = eventInfo?.EventHandlerType;
            var window = Window.GetWindow(o);
            var method = window.GetType().GetMethod(AttachedEvents[eventName]);
            var handler = Delegate.CreateDelegate(eventType, window, method);
            eventInfo.AddEventHandler(o, handler);
        }

Aus Zeile #5 kann das EventInfo als null hervorgehen, etwa wenn ein unsinniger EventName angegeben ist (glaubich jds, müsste man testen, oder Doku lesen).
Imo sollte man da eine Exception werfen, aber bei dir wird das laufengelassen, bis schließlich ein handler createt wird, bei dem sowohl eventType als auch method nichts rechtes sein können.

Wie gesagt: Wenn da ein ungültiger EventName gegeben ist, wird das komisch.
Hingegen den Test, ob o null ist, kannste dir sparen: o kann nicht null sein, denn an null kann nichts attached werden.

So insgesamt habich den Eindruck, das ganze macht ungefähr dasselbe, was auch ein Tooltip machen täte, also ich will jetzt nicht, sagen, dass du da vlt. das Rad neu erfindest, aber ich sags trotzdem :evil:

Was mir noch fehlt ist, dass der Text auch wieder verschwindet, wenn man vom Control runter ist.

Der Vorzug der 2. Variante ist mir auch nicht ganz klar, ich mag die erste lieber, sind ein paar Zeilen weniger.

05.03.2016 - 18:36 Uhr

och - ich finds ganz ok.

Ich hätt vmtl. das RoutedEvent des Windows behandelt, und wäre da beim MouseMove immer den VisualTree hochgelaufen oder sowas.

Und ich hätte es eher Daten-Orientiert gemacht, also dass ich nicht Controls überwache, sondern letztlich, ob der User mitte Maus über einem meiner Viewmodel-Präsentationen steht.

Aber ist bischen anderer Use-Case.

04.03.2016 - 19:32 Uhr

ich kann nix zu sagen, weil ich kanns nicht nachbauen.
vlt. magstes in die Snippets einstellen - da kann ichs dann runterladen, rumprobieren, und mein Senf zu geben?

03.03.2016 - 12:24 Uhr

ähm - wärest du evtl. interessiert, Databinding zu erlernen?

Weil ohne Databinding artet eine Datenverarbeitung sehr schnell in sehr große Mengen Code aus, und kaum wartbar.

02.03.2016 - 14:12 Uhr

nein, je wie die Db konfiguriert ist, werden Statements automatisch erzeugt.

Aber wenn deine Db-Tabelle zB keinen Primärschlüssel hat, dann können keine Update- oder Delete-Commands generiert werden, bleiben also null.

Dann findest du auch nur das SelectCommand. (vlt. auch noch ein InsertCommand, weiß ich aber nicht.)

01.03.2016 - 22:49 Uhr

Meine Antwort hast du bereits - Stichwort "Datenmodellierung".

Ganz neu und von Anfang lernen, vermutlich auch noch grundlegendere Grundlagen.

Es kommt mir sehr eigenartig vor, dass du scheints 4 DGVs hast, die heissen wie die Staffeln einer Serie.
Wenn ich das weiter-denke, dann kannst du ja nur dann Serien hinzufügen, indem du in den Editor gehst, und weitere DGVs anbringst, etwa dgvMonk1, dgvMonk2, ...

Und dann neu kompilieren.

Ist das so konzipiert bei dir?

01.03.2016 - 16:31 Uhr

ich denke, das Problem sind bei solchen Sachen nicht die Controls, sondern das Datenmodell.

Meist, wenn Leutz viel über Controls reden und nachdenken, dann deshalb, weil sie das Konzept Datenmodell überhaupt nicht kennen.

Andersrum - kennt man sich in Datenmodellierung aus (soo schwierig ist das garnet) - dann findet man auch recht leicht zu geeigneten Präsentationen der Daten.

Bzw. ist dann auch kein Thema, eine Präsentation zu ändern, oder geeigneteres zu schaffen.

Die Crux ist immer, dass das Datenmodell stimmig sein muss.

Habich 3 Codeproject-Artikel zu gemacht:
http://www.codeproject.com/Articles/1030969/Relational-Datamodel-for-Beginners

01.03.2016 - 13:53 Uhr

Komische Frage.

Du hast da doch einen Link, der sie beantwortet. Ich hab den Film nicht gesehen, also sag du mir: ruft Beth Massi die ganze Tabelle neu ab, nachdem sie ein Update ausführt?

Oder du guckst dir doch mal das an, was ich dir verlinkt habe - ich hab den starken Eindruck, du hast ihn garnet aufgesucht.

01.03.2016 - 10:06 Uhr

sollte kein Prob sein - ist im Link ja vorgeturnt.

Zu beachten ist, dass du die DataRelation zwischen Parent und Child richtig konfigurierst:

AcceptRule.None
DeleteRule.Cascade
UpdateRule.Cascade

UpdateRule.Cascade sorgt dafür, dass wenn du beim re-query der ID diese in die ParentRows einpflegst, dass dann die ChildRows ihre Foreignkeys nachführen.

29.02.2016 - 22:51 Uhr

Warum erstellst du ein komplettes neues Dataset, befüllst es komplett, nur um eine einzige DataRow zuzufügen?

Hast du nicht zufällig iwo ein bereits befülltes Dataset? Meist hat man eines, weil sonst kann die Anwendung ja garnix anzeigen.

Wenn zu was hinzufügen willst, füge da was hinzu - nicht extra ein neues erstellen und befüllen (weil das geht ja an dem vorbei, was du schon hast, und dann siehst du ja auch nix (mal vonne Performance abgesehen)).

Also wenn man mit Databinding arbeitet, muss man sich genau überlegen, was das Schlüsselwort new bedeutet, und obs das wirklich ist, was man will.

Ansonsten hast du vmtl. das Problem, dass deine Datenbank die Primkeys vergibt.
Wenn du also einen ParentDatensatz abspeicherst, bekommt der vonne Db einen neuen Primkey.
Und zu diesem Primkey passt dann der ForeignKey der nun folgenden ChildRow nicht mehr.
Man muss also, wenn man einen Datensatz mit autoIncrement abspeichert, immer den neu generierten Primkey zurück-abfragen, und ins Dataset einpflegen.
Ist bei OleDb umständlicher als mit SqlServer, aber geht auch - siehe hierzu https://www.vb-paradise.de/index.php/Thread/40718-Auslesen-des-neuen-Wertes-der-Schl%C3%BCsselspalte-nach-dem-Erstellen-eines-neuen-Dat/#

(das einfachste ist natürlich, die Db insgesamt wegzulassen, und das Dataset einfach in eine Xml-Datei zu speichern - bis ca. 20000 Datensätzen ist das bestimmt kein Problem)

29.02.2016 - 14:27 Uhr

ich hoffe, du nimmst es mir nicht übel, wenn ich anmerke, dass der CodeProjekt-Artikel zwar Locking-Mechanismen durchgenimmt, aber soweit ich sehe, kein Beispiel unter Einbezug von EF enthält.

Also die Formulierung "Locking umsetzen mit EF" erweckte in mir falsche Erwartungen an den Artikel.

26.02.2016 - 11:19 Uhr

sieht sehr interessant aus, aber bischen ville, ums zu durchblicken.
V.a. sehe ich nix, wo nun die Daten eiglich geladen werden.

Und das generiert jetzt wirklich sone Oberfläche, wie in post#4 abgebildet?

Falls ja - magst du das vlt. zippen und in die c#-Snippets stellen?
Da können noch mehr Leuts was von haben, denkich.

26.02.2016 - 11:08 Uhr

Funktioniert ein Typed Dataset überhaupt in Verbindung mit MS Access? ja sicher.
Dem Dataset ists egal, ob es in eine Db persistiert oder einfach mit .Write-/Read-Xml() auf Platte. Das kann man sogar nachträglich noch umändern.

Bei mit Db ist nur wesentlich mehr zu beachten, weil wie gesagt das Datenmodell zweimal umgesetzt werden muss, in zwei gänzlich unterschiedlichen Systemen.
Erfordert also auch noch eine Vermittler-Schicht dazwischen, und alles drei muss erstmal aufgesetzt, und dann die ganze Entwicklungszeit immer perfekt aufeinander abgestimmt sein.

Hingegen ohne Db kann man prototypisch datasetOnly sehr zügig entwickeln, und wenns dann in Richtung Alpha-Version geht, die Db immer noch dranpatchen.
Weil ist ja nicht unwahrscheinlich, dass ein Produktiv-System mit sone Winz-"Embedded-Database" nicht mehr auskommt.

26.02.2016 - 09:13 Uhr

Hi!

Ich konnts nicht lassen, und habs noch weiter ausgeführt, und habich in die Snippets gepackt:
Kleine Datenverarbeitung DatasetOnly
Da kann mans jetzt angucken und probieren, diskutieren, Erweiterungen, Verbesserungen, Alternativen posten - am besten wäre natürlich mit angehängten, lauffähigen Zips, auf der Vorlage basierend oder auch from Scratch.

26.02.2016 - 02:47 Uhr

Hier noch der Zip-Anhang, und Code:

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;

namespace QuizApp {
   public partial class frmQuizApp : Form {
      private FileInfo _DataFile = new FileInfo(@"..\..\Data.xml");
      public frmQuizApp() {
         InitializeComponent();
         btLoad.Click += btLoad_Click;
         btSave.Click += btSave_Click;
         LoadData();
      }

      void btLoad_Click(object sender, EventArgs e) { LoadData(); }

      void btSave_Click(object sender, EventArgs e) {
         if (!this.Validate()) return;
         quizDts.WriteXml(_DataFile.FullName);
         quizDts.AcceptChanges();  // Doku lesen! AcceptChanges() bei hinterlegter Datenbank **nicht** verwenden! Unbedingt vorher Doku lesen und **verstehen**
         System.Media.SystemSounds.Asterisk.Play();
      }

      void LoadData() {
         quizDts.QuizFrage.ColumnChanged -= QuizFrage_ColumnChanged; // Event vor Massen-Operationen deaktivieren
         var bss = components.Components.OfType<BindingSource>().ToArray();
         foreach (var bs in bss) bs.RaiseListChangedEvents = false;
         quizDts.Clear();
         quizDts.ReadXml(_DataFile.FullName);
         quizDts.AcceptChanges();  // Doku lesen! AcceptChanges() bei hinterlegter Datenbank **nicht** verwenden! Unbedingt vorher Doku lesen und **verstehen**
         foreach (var bs in bss) {
            bs.RaiseListChangedEvents = true;
            bs.ResetBindings(false);
         }
         quizDts.QuizFrage.ColumnChanged += QuizFrage_ColumnChanged;
      }

      void QuizFrage_ColumnChanged(object sender, DataColumnChangeEventArgs e) {
         if (e.ProposedValue == null) return;
         quizDts.QuizFrage.ColumnChanged -= QuizFrage_ColumnChanged; // Event deaktivieren, sonst Selbst-Auslösung
         var tb = quizDts.QuizFrage;
         foreach (var col in new DataColumn[] { tb.SpellFrageIDColumn, tb.MCFrageIDColumn, tb.BildFrageIDColumn }) {
            if (col != e.Column && !e.Row.IsNull(col)) e.Row[col] = Convert.DBNull;
         }
         quizDts.QuizFrage.ColumnChanged += QuizFrage_ColumnChanged;
      }

      protected override void OnClosing(CancelEventArgs e) {
         if (quizDts.HasChanges()) {
            switch (MessageBox.Show(this, "Save Changes?", "Save Changes?", MessageBoxButtons.YesNoCancel)) {
            case DialogResult.Yes: btSave.PerformClick();
               break;
            case DialogResult.No:
               break;
            case DialogResult.Cancel: e.Cancel = true;
               break;
            }
         }
         base.OnClosing(e);
      }
      protected override void OnClosed(EventArgs e) {
         tabControl1.Dispose();
         base.OnClosed(e);
      }

      private void mCAntwortDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e) {
         var grd = (DataGridView)sender;
         if (grd.Columns[e.ColumnIndex].DataPropertyName != "IsTrue") return;
         var rwAntw = (QuizDts.MCAntwortRow)((DataRowView)bsMcFrageMcAntwort.Current).Row;
         var rwFrage = rwAntw.MCFrageRow;
         rwFrage.MCAntwortRow = rwFrage.MCAntwortRow == rwAntw ? null : rwAntw;
      }
   }
}

Also es ist noch "Klumpen-Architektur" 😉 , das würde man beim Weiter-Entwickeln diversifizieren.
Es ist auch nicht absturz-sicher, kann noch keine Bilder anzeigen, und wie man das Quiz nun spielt, hab ich mir noch nichtmal was zu ausgedacht.
Also falls sich jemand für interessiert, oder gar Lust hat, auch bischen was dran zu basteln, würde ich auch noch bischen weiter machen ansonsten lass ich das auf diesem "Proor-of-concept"-Stand.

geproofte Konzepte wären*streng typisiertes, relationales Datenmodell *Abspeichern und Laden ohne Db - die Xml ist sogar einfach in den Sources anzugucken 🙂

*databinding-getriebene Oberfläche *crud-komplett (lesen, schreiben, ändern löschen aller Datensätze) *Save-Changes-Abfrage beim Schließen *Lösung des Problems der verschiedenen Frage-Typen *Lösung des Problems der Multiple-Choice-Antworten

26.02.2016 - 02:42 Uhr

Noch Bildle der Quiz-Zuordnungs-Ansicht:
Man sieht den ersten Quiz, und der hat 5 Fragen, und jede Frage verweist auf nur einen Frage-Typ.
Unten in der Zufügezeile kann man weitere Fragen zufügen.
In der vorletzten Zeile bin ich grad im Begriff, eine andere Frage anderen Typs zuzuordnen. Wenn ich das bestätige, wird dann die McFrage derselben Zeile genullt.

26.02.2016 - 02:35 Uhr

Anbei der Anfang einer "Quiz-Anwendung"

Das Konzept ist entstanden aus dieser Diskussion: Wie designe ich die Datenbank für ein Quiz mit drei verschiedenen Fragearten? und setzt sie quasi etwas fort.
Ihr könnt gerne - wenn ihr wollt - Antworten posten, Erweiterungen, Verbesserungen, Alternativen - am besten wäre natürlich mit angehängtem, lauffähigen Zips, auf der Vorlage basierend oder auch from Scratch.

Datenmodell
Bildle gugge: QuizFrage ist Zuordnungstabelle einer m:n - Relation, deren Datensätze jeweils eine Frage einem Quiz zuordnet.

Problem1: Polymorphie
Das komplizierte ist jetzt, dass es 3 verschiedene Arten von Fragen gibt:1.SpellFrage: verlangt eine buchstaben-getreue Antwort 1.BildFrage: Ein Bild wird gezeigt, dazu eine Frage, ebenfalls buchstaben-getreu zu beantworten 1.McFrage - **M**ultiple **C**hoice: Mehrere Antwortmöglichkeiten, von denen eine richtig ist

Es handelt sich also um ein Polymorphie-Problem, und OOP-mäßig würde man dazu neigen, etwas mit geerbten Basisklassen oder Interfaces zu versuchen.
Richtige Polymorphie wird aber vom Dataset nicht unterstützt, und würfe auch Präsentations-Probleme auf, die imo erst in Wpf eine wirkliche Antwort finden (DataTemplates).

Hier ists so gelöst, dass ein QuizFrage-(Zuordnungs-)Datensatz gleich 3 Verweise hat, auf jede Frage-Art einen.
Business-Logik muss nun sicherstellen, dass immer mindestens 2 der Verweise genullt sind - anders gesagt: Dass ein Zuordnungs-Datensatz nur eine Frage zuordnet, nicht 3 verschiedene auf einmal.
Diese "Umgehung der Polymorphie" erweist sich bei der Präsentation als überraschend praktisch: Dem User werden die verschiedenen Frage-Arten ja als Spalten präsentiert, und indem er in eine Spalte eingibt hat er bereits die Art der zugeordneten Frage bestimmt.
😁

Problem2: Multiple Choice
Ein anderer Trick ist die wechselseitige Relation zwischn McFrage und McAntwort:
Nämlich eine McFrage hat logisch viele Antwort(-Optionen), ist also übergeordnet.
Aber gleichzeitig hat sie auch einen Verweis (also einen Fremdschlüssel, untergeordnet) auf die richtige Antwort.
Gui-Logik sorgt nun dafür, dass wenn die DGV-Checkbox-Zelle der IsTrue-Spalte angeklickt wird, dass dann die Parent-Frage ihren Verweis auf diese Antwort setzt.
IsTrue ist übrigens eine berechnete Spalte, darin gar kein Wert eingebbar ist, sondern sie berechnet sich selbst, mit folgender Expression (eingetragen im Dataset-Designer):
count(child.ID)=1
also wenn es genau eine ChildRow gibt, ist dieses die richtige Antwort.
Da die ChildRow einer McAntwortRow aber gleichzeitig immer auch die ParentRow (McFrageRow) ist, kann es zu einer Antwort auch nur maximal 1 ChildRow geben.
Und wenn es sie gibt ist damit IsTrue true, und diese Antwort also als die einzig richtige gekennzeichnet 😁
(ups - mir fällt grad auf: das ist ja gar kein Multiple-Choice, da ist ja nur Choice 8o)

25.02.2016 - 21:50 Uhr

wenn du dich damit beschäftigst, beachte die Links aus post#5 - das kann dir sehr viel Zeit ersparen.
Ich kenn das, wenn Threads länger werden, werden die wichtigsten Sachen schnell übersehen.

25.02.2016 - 21:38 Uhr

Wenn dein Model unersetzbar sein sollte,... Es ist bereits umgesetzt - du siehst ja das Bildchen.
Das ist eben das feine an Wysiwyg, dass was man angucken kann, gleichzeitig kompilierten, nutzbaren Code darstellt.

..., sollte meines auch funktionieren. eher nicht. Ist ja nur hingeschrieben, und wurde noch kein kompilierbarer Code für generiert (oder gecodet).

Knackpunkt ist das Polymorphie-Problem, also die Idee, dass der Fremdschlüssel eines Frage-Datensatzes entweder auf eine BildFrage, oder auf NormalFrage, oder auf MCFrage verweisen können soll.
Dieser Gedanke ist naheliegend, und wär schön, aber geht numal nicht, nicht mittm Dataset, und ich glaub auch nicht in Access oder EF oder sonstwo.

Allenfalls mit einem komplett von Hand gecodetem Datenmodell ist das denkbar, und dazu ein händisch gecodetes DAL, und das DAL muss tricksen, also per Code die polymorphe Relation gewährleisten, die in der Datenbank garnicht formulierbar ist.

Ich denke, da kommst du ganz schnell auf über 500 Zeilen händischen Codes, wo ich immernoch nicht mehr als meine beiden Zeilen brauche: Dataset.Read-/Write-Xml()
Und (ich bin noch nicht fertig 😉 ) du hast das ganze Gschiss mit dem zweifach umgesetzten Datenmodell, und der Adapter-Schicht dazwischen, was alles immer peinlich genau aufeinander abzustimmen ist.

25.02.2016 - 20:17 Uhr

p.s.
@ErfinderDesRades
Meine Tabellen sehen ein bisschen anders aus als deine 😉 Ja, und ich glaub, dein Modell kannst du auch in einem typDataset kaum umsetzen.

Das wär aber besser, weil was im typDataset umgesetzt ist, damit kann man gleich los-programmieren, Daten generieren, Databinding und so.

25.02.2016 - 16:45 Uhr

Hm - bei mir werden die Controls auch dynamsich erzeugt. Das geschieht aber über Templates.
Also im Code generiere ich Viewmodels, und angebundene Xaml-Templates machen Controls davon.
Im Zeichenprojekt da werden halt keine Buttons davon gemacht, aber Controls sinds auch.

Also wenn du Buttons sehen möchtest, gugge
https://www.vb-paradise.de/index.php/Thread/92049-TicTacToe/
oder - fast noch hübscher:
https://www.vb-paradise.de/index.php/Thread/102270-Kein-Pong-Erstaunliches-mit-ItemsControl-Itemspanel/
(ist glaub auch leichter verständlich)

25.02.2016 - 16:18 Uhr

ok, dann kannste halt 3 verschiedene Tabellen für die 3 verschiedenen Arten Frage anlegen.
Eine Relation zwischen denen besteht nicht, sondern es muss noch die Tabellen Quiz und QuizFrage geben, die allen 4 anderen Tabellen untergeordnet ist.
Ein QuizFrage-Datensatz hat also Verweise auf das Quiz und auch auf alle 3 Fragen.
Nur durch Businesslogik kannst du dafür sorgen, dass 2 dieser Verweise immer genullt sind.

Ich würd dir übrigens sehr empfehlen, die Datenbank wegzulassen.
Das wird alles noch höchst kompliziert, und das Datenmodell wird sich noch zig-mal ändern.
Da ist das immer nur ein fürchterlicher Klotz am Bein, wenn du die ganze Entwicklungszeit diese unhandliche DB-Kommunikation mit rumschleppst.

Ich weiß, das glaubt mir niemand, dass man Daten viel einfacher mit Dataset.WriteXml(filePath) auf Platte beamt, als mit DataAdaptern, EntityFramework oder gar mit DbCommands, Connections, Readern und und und.

Ah - ein Argument bringe ich noch:
Die Oberfläche databinding-getrieben zu entwickeln - das ist der Hauptpunkt, und die eigentliche Aufgabe einer Datenverarbeitung.
Databinding erfordert zwingend ein typisiertes Datenmodell.
Das heisst, so oder so muss das Datenmodell - was ja eigentlich nur ein Konzept ist, in Code umgesetzt sein - so oder so.
Wenn du nun dir eine Datenbank ans Bein bindest, dann musst du dasselbe Datenmodell ein zweites mal umsetzen - diesmal nicht in c#-Code, sondern nun in Form von letztlich Sql-Code.
Damit hast du dasselbe DM zwiemal auf grundverschiedene, und vollkommen inkompatible Weisen umgesetzt, und dennoch müssen beide Umsetzungen einander zu 100% entsprechen.
Und dann hast du das Vergnügen, eine Vermittlungs-schicht zwischen die beiden Modell konstruieren zu dürfen, damit Daten von einem Datenmodell ins annere fließen können.
Und jede Veränderung wirft das ganze Konstrukt über den Haufen, und jede kleine Abweichung der Modelle untereinander führt zum Crash, aber in der Vermittlungs-Schicht kann eiglich ebensoviel schieflaufen.

Alles unnötig.
Denn du kannst mit Dataset.Read-/Write-Xml ein Dataset-Datenmodell auf Platte schreiben und laden - eine Codezeile, nur ein Datenmodell, keine Vermittlerschicht.
Es ist wirklich einfacher.

Gut Pladoyer-Ende.
Wenns dich interessiert, habich hier ein 3-teiliges Tut verzapft, das fängt bei Adam+Eva an, und vermittelt glaub alles erforderliche Handwerkszeug:
http://www.codeproject.com/Articles/1030969/Relational-Datamodel-for-Beginners

Einen Vorgeschmack vom databinding-getriebenem Entwickeln kannst du auch auf Video haben:
http://www.vb-paradise.de/index.php/Thread/94955-die-vier-views-auf-video/#post798777
Weil es geht ratzfatz, wenn mans verstanden hat, und man versteht die Stärke des Ansatzes eiglich nur, wenn mans in Aktion sieht.

Hier, ich hab mal ein denkbares Modell angehängt. Der Witz ist die wechselseitige Relation zwichen MultipleChoice-Frage (MCFrage) und MCAntwort.
Weil eine MCFrage kann ja viele Antworten haben. Aber ausserdem sollte sie auf genau eine Antwort verweisen, die richtig ist.

25.02.2016 - 15:39 Uhr

Das mit Antwort eingeben wird kaum funktionieren.

Die natürliche Sprache hält immer hunderte von Formulierungs-Möglichkeiten bereit, dieselbe Frage richtig zu beantworten.

Es sei denn, die Frage fragt nach einem einzigen Wort, und das muss richtig geschrieben sein.

25.02.2016 - 15:29 Uhr

Guck doch in den verlinkten downzuloadenden Code, und sag du's mir: Mache ich dann alles in XAML?

25.02.2016 - 09:19 Uhr

Uih - das wird knackig!

Ich würde auf ein Grid als ItemsPanelTemplate eines ItemsControls setzen, mit vom Viewmodel gesteuerten Zeilen und Spalten.

Dann brauchst du einen sehr listigen Algo, der die Termine durchgeht, und Überlappungen feststellt, auch das n bei n-fachen Überlappungen - dieses n definiert ja die Spalten-Anzahl.

Und dann aus den Terminen Viewmodelse bilden, mit bindebaren Properties für Zeile, Spalte, RowSpan.

Sorry - ist nur grob angedacht - für konkreteres müsste ich selbst stundenlange Experimente machen.
Evtl. muss man sogar von Grid erben, und was basteln, damit das Grid seine Row-/Column-Definitions per Bindings steuern kann - weiß nicht.

24.02.2016 - 13:37 Uhr

Noch zur Erläuterung der Nachfrage - obwohl dir dein Prob als gelöst scheint:

Eventuell ist deine Klasse verbesserungsfähig:

Zum einen ist evtl. möglich, den .OfType() - Cast überflüssig zu machen, mit Gewinn für Lesbarkeit und Performance.

Zum anderen baust du dir evtl. eine fehlerhafte Verarbeitung auf, die ermöglicht, Objekte in Listen zu tun, die da nicht reingehören. Solch kann entweder Abstürze verursachen, oder aber auch "nur" sehr unauffälliges Fehlverhalten, wie dass Berechnungen manchmal falsche Ergebnisse liefern und Scherze.

Wie gesagt: Kann sein oder auch nicht - man müsste wissen, wie's wirklich aussieht in der Klasse - meinetwegen auch nur beispielhaft verkürzt, aber die Verkürzung sollte schon kompilieren.

24.02.2016 - 12:28 Uhr
IList<ISchnittstelle> liste = new List<Klasse1>();  

kompiliert nicht - wie sieht das wirklich bei dir aus?

24.02.2016 - 12:19 Uhr

Doch es können x Termine für den Zeitraum gebucht werden. Das ist problematisch, schwierig zu handeln und müsstest du mal näher erläutern.

Wie kommt zustande, dass zum selben Zeitpunkt mehrere Termine stattfinden, und wieso sollten die überhaupt in derselben View angezeigt werden?

Auch habich Mühe, mir das in Spalten vorzustellen - in meiner Welt hat eine Spalte eine Spalten-Überschrift, aber womit überschreibt man eine Spalte, die mal da ist, mal nicht?

24.02.2016 - 11:51 Uhr

Wie auf die Sprünge helfen?

Sollte dies nicht nur jeweils einmal passieren? Wie's aussieht passierts halt mehrmals.

Du könntest allenfalls ein stark vereinfachtes Test-UserControl basteln, und damit herumprobieren.
Vielleicht kannst du ja näheres feststellen, unter welchen Umständen es wie oft aufgerufen wird.

Denkbar ist, dass im CustomControl ungeschickt angelegte Logik zu häufigeren Aufrufen führt.
Auch denkbar ist, dass ein besonders listiges CustomControl seine Abmasse iwie cacht, sodass auch viele MeasureOverride-Aufrufe nicht auf die Performance hauen.

Denkbar halt, eigene Erfahrung habich damit nicht.

23.02.2016 - 19:15 Uhr

ErfinderDesRades:
Man'n' soll bzw muss ja schließlich das Pattern zu 100% umsetzten. 😄 Findich nicht. Ich setze mich ganz oft völlig rücksichtslos über iwelche Pattern oder Pattern-Details hinweg, wenn mir deren Gewinn nicht plausibel ist.

Und im Übrigen bist du ziemlich entfernt davon ieinen Pattern 100% umzusetzen.

Für so ein kleines Lernprojekt müsste aber ein VM ja auslangen.

Aber mit einander kombiniert ist es schon zufriedenstellend. 😄
Ist es überhaupt nicht.
Wie gesagt: Anders als andere Teilnehmer dieses Threads nehme ich die genaue Einhaltung (100%) aller Pattern-Bestimmungen nicht so wichtig.

Was ich wichtig nehme, ist, ob ein Modell das Modellierte auch richtig nachahmt. Denn andernfalls ist es MÜll.
Ein Viewmodel modelliert nun einen View, und dein View zeigt eine Liste von Kontakten.
Das heisst, der View zeigt eine Liste, und viele Kontakte.
Das sind 2 grundverschiedene Sachen: (Kontakt-)Liste und Kontakt.
Sowas im Modell des Views (dem Viewmodel) dann zusammenzuschmeissen ist einfach Unfug.
Realo-Beispiel:
Ein Bus ist ein Container für Menschen. Bus und Mensch sind aber völlig verschiedene Dinge, und wollte man das zu einem Ding machen, käme etwas bei raus, wo man in den Busfahrer einsteigt oder sowas.
Halt einfach Unfug - NoGo.
Wenn du eine Auflistung von Objekten nicht vom einzelnen aufgelisteten Objekt unterscheiden kannst, dann kannst du imo als Programmierer nicht klarkommen.

23.02.2016 - 08:26 Uhr

ich vermute, du willst eigentlich das SelectedItem des Datagrids binden.
Weil das SelectedItem einer Combobox im CellTemplate zu binden dürfte zu Fehlfunktionen führen.

22.02.2016 - 13:30 Uhr

Beachte, dass MarcelM esl prinzipiell ok findet, alles in einem Viewmodel abzuhandeln - ich aber nicht.

Für mich müssen 2 Viewmodel-Klassen her: 1.ContactVM
stellt einen Contact dar

1.ContactCollectionVM
stellt viele Contacts dar, sowie den SelectedContact und Funktionalität zum Zufügen/Löschen von Contacts

Also du wirst evtl. nicht alle Anregungen von jedem einbeziehen können, denn wir widersprechen uns 👅

21.02.2016 - 17:06 Uhr

Ähm - ich hab dir nix verboten.

21.02.2016 - 16:55 Uhr

Mag sein - also ich guck jetzt erstmal auf das Viewmodel wie's ist.

Mir scheint ContactsViewmodel paradox aufgebaut:
Ist das nun ein Viewmodel eines Contacts oder ist es das Viewmodel einer Auflistung von Contacten?

Das ist iwie durchmischt.
Weil wenn es ein einzelner Contact ist, dann sind die Properties Name, Vorname etc. richtig.

Aber dann haben Properties wie SelectedContact da nix verloren, denn der SelectedContact ist logisch Member einer Auflistung vieler Contacte.

Und dementsprechend auch die Benamung: Wenn das gezeigte Viewmodel einen Contact repräsentiert, darf es nicht als plural benannt sein.

Ein plural-Viewmodel scheint also zu fehlen, wäre aber vonnnöten, und das enthielte die ObservableCollection<Contact>, und den SelectedContact, und enthielte (oder stöße zumindest an) die Logik zum Hinzufügen, Löschen, abspeichern.

21.02.2016 - 16:43 Uhr

Schön und gut, aber was nützt das DerPapenberg?
Ich fürchtefast, was du vorschlägst, ist für ihn (im Gegensatz zur oben gezeigten Serialisirungs-Lösung) kaum nachvollziehbar.

21.02.2016 - 13:13 Uhr

hihi - gelegentlich betätige ich mich als Defätist, und sage Sachen wie
"Linq wird total überbewertet. Die gute alte foreach-Schleife kann mehr, ist oft schneller entwickelt, ist performanter und leichter verständlich"

:evil:

Aber wenn die Zahl der Header-Zeilen immer gleich ist, kannst du noch ein .Skip(6) einschieben, dann gehts wieder.

Ich würd die Linq-Lauf-Variable übrigens anders nennen, es ist sehr verwirrend, wenn etwas list heisst, aber gar keine Liste ist.
Ausserdem reichts, nach int zu parsen - sind ja ganze Millisekunden.
Die Daten sind Messwerte, oder?

Dann ist die Suche auch inperformant, zumindest könnte sie ja beim ersten Treffer abbrechen - es ist ja ein sortierter Datenbestand, und der SampleTime-Wert ist ja unique, wie's aussieht.

21.02.2016 - 11:21 Uhr

So müsste es stimmen:


         var query = from list in
                        (from line in File.ReadAllLines(@"D:\ SCREENING_450_NIEDER.txt")
                         let personalrecord = line.Split(';')
                         select new {
                            Sampletime =double.Parse( personalrecord[0]),
                            NE = personalrecord[1],
                            TH = personalrecord[2],
                         })

                     where list.Sampletime == 50.0
                     select list;

         foreach (var item in query) {
            Console.WriteLine(item.Sampletime);
         }

Wenn du eine Exceptions kriegst, dann liegt das an ungeeigneten Daten. Aber das wird die Exception dir auch sagen.

(Übrigens: Linq ist kein Datenbank-System)

21.02.2016 - 07:47 Uhr

wenn auf eine Db verzichtet werden kann, ist das natürlich ein riesen-Vorteil - ich wüsste jetzt nicht, was an einer Datenbank einfach sein sollte - dassis im Gegenteil die anspruchsvollste Persistierung, die denkbar ist.

Die wirklich einfachste Persistierung wäre, die TreeNodes einfach mit einem XmlSerializer auf Platte zu schreiben. Das geht in 5 Zeilen umzusetzen.

Sorry - mit XmlSerializer gehts nicht so direkt. aber mit BinaryFormatter kann mans serialisieren:

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TreeviewPersist {
   public partial class frmTreeviewPersist : Form {

      private FileInfo _Data = new FileInfo(@"..\..\Data.dat");

      public frmTreeviewPersist() {
         InitializeComponent();
      }

      private void btSave_Click(object sender, EventArgs e) {
         var nodes = new TreeNode[treeView1.Nodes.Count];
         treeView1.Nodes.CopyTo(nodes, 0);
         _Data.Serialize(nodes);
      }

      private void btLoad_Click(object sender, EventArgs e) {
         var nodes = _Data.Deserialize<TreeNode[]>();
         treeView1.Nodes.AddRange(nodes);
      }

   }


   public static class SystemIOX {
      /// <summary>Achtung! FileInfo.OpenWrite ist ungeeignet, denn es erneuert nicht unbedingt die ganze Datei</summary>
      public static void Serialize(this FileInfo fi, object obj) {
         using (var strm = fi.Open(FileMode.Create)) strm.Serialize(obj);
      }
      public static void Serialize(this Stream strm, object obj) {
         (new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()).Serialize(strm, obj);
      }
      public static T Deserialize<T>(this FileInfo fi) {
         using (var strm = fi.OpenRead()) return strm.Deserialize<T>();
      }
      public static T Deserialize<T>(this Stream strm) {
         return (T)(new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()).Deserialize(strm);
      }
   }
}

Du solltest aber ein paar Nodes im FormDesigner angelegt haben, denn das hier persistiert nur - Nodes bearbeiten ist ein anderes Kapitel.

20.02.2016 - 20:19 Uhr

Jetzt weis ich nur nicht wie ich, wenn im DG ein Kontakt ausgewaehlt ist die Daten an die tbx uebergebe. na, das hab ich dir doch gesagt.
Es hat nu keinen Sinn, da weiter drüber zu filosofieren, solange du's nicht einfach mal ausprobierst.
(kann ja auch sein, es funzt net)

20.02.2016 - 18:43 Uhr

also eine recht primitive Version findeste hier: http://www.codeproject.com/Articles/1077556/Populating-TreeView-up-to-N-Levels-in-Csharp-from

Ich bin zwar äusserst unbegeistert, was der mit dem Dataset anstellt, aber immerhin es läuft.

20.02.2016 - 18:36 Uhr

hängt natürlich vom DataContext ab, aber könnte mir vorstellen, dass sowas funzen täte:

 <TextBox Text="{Binding SelectetContacts.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="5,0,0,0"/>

Ich würd aber sehr empfehlen SelectetContacts umzubenennen zu SelectetContact, also Singular.

19.02.2016 - 07:13 Uhr
<TextBox Text="{Binding Betrag, ConverterCulture='de-DE', StringFormat=0.00, UpdateSourceTrigger=PropertyChanged}"   />  

Datentyp double?
Gebe ich nun eine ganze Zahl ein dann wird diese mit den Nachkommastellen ergänzt, will der Benutzer nun eine Kommazahl eingeben steht das Komma schon drin und er hat ein zweites Komma in der Textbox. Vielleicht hilft eine TemplateColumn.
Da kannst du als CellTemplate stringFormat 0.00 festlegen, und als CellEdditingTemplate stringFormat 0.##. Ich glaub jdfs, dass # das Format-Zeichen für optionale (Nachkomma-)Stellen ist.
Ansonsten nochmal MSDN-Doku konsultieren.

17.02.2016 - 19:17 Uhr

naja, als Value wird dir ja ein String gegeben.
Wenn du aus diesem String nicht beides heraus-lesen kannst, sowohl Typ als auch LowerBorder, dann kann logischerweise keine Rück-Conversion stattfinden.