Laden...

Forenbeiträge von ErfinderDesRades Ingesamt 5.299 Beiträge

04.04.2016 - 15:36 Uhr

Hier in meiner Artikel-Serie (im 3. Artikel) entwickel ich gegen Schluss hin ein datengebundenes Dialog-Wesen, was bereits vom Konzept her immer dazu ausgelegt ist, Datensätze entwederzu editieren oder neue anzufügen + editieren.
http://www.codeproject.com/Articles/1035182/typed-programming-the-typed-Dataset-for-Beginners
Also das Tut enthält jede Menge weiteren Stoff zum Thema Databinding, ist halt die Frage, wieviel davon du überspringen kannst, und trotzdem die Dialog-Sache noch umsetzen.

Lohnt sich auf jeden Fall - nicht nur vom Databinding her - die meisten wissen gernet, wie umfassend WinForms es unterstützt, ein Dialog-Form aufzusetzen.

Mit "DialogWesen" meine ich genaugenommen 2 Extension-Methods, die im stande sind, geeignete als Dialog angelegte Forms auch als Dialog (modal) zu öffnen, und auch das DialogResult entsprechend zu verarbeiten, je nachdem ob .Cancel oder .Ok
Wie gesagt die eine Extension ist zu Editieren eines vorhandenen Datensatzes, die andere für NeuAnlage - und beide verwenden dasselbe (Dialog-)Form, was ihnen übergeben wird.

Edit:
Achso, sorry. Du willst ja ausserdem noch eine Readonly-Präsentation. Dass liesse sich durch eine 3. Extension bewerkstelligen, die beim Schließen halt immer Cancel auslöst. Aber wäre vonne Optik her nicht perfekt, denn die Controls wären nachwievor editierbar, nur würde es nicht übernommen.

03.04.2016 - 13:30 Uhr

sieht richtig gebunden aus.

tja, wenn die Combo nix anzeigt, kanns auch dran liegen, dass die BindingSource keine Daten hat.

01.04.2016 - 08:56 Uhr

Jo, da kann man einiges zu sagen, wann was günstiger ist.

Bei mir ist häufiger vor-evaluierung angezeigt, weil ich meine Listen leicht überwiegend mehrfach benutze.
Aber ist eh zu 99% irrelevant, denn nur ganz ganz selten habich mit Datenmengen von auch nur über 100 Stück zu tun - das wäre nichtmal schlimm, es mehrfach zu evaluieren.

01.04.2016 - 08:26 Uhr

(Obwohl ich die ()=> schreibweise bevorzuge) Jo, dem neige ich jetzt auch zu, wenn ich so Vergleiche ziehe:


         { 
            var result2 = from p in products group p by p.CategoryId into g select g;
            var result3 = products.GroupBy(p => p.CategoryId);
         }

Die Linq-Syntax hat 11 Wort-Zwischenräume (also textuelle Einheiten zu beachten), die Lambda-Schreibe nur 2 - oder mw. 4, wenn man Klammern auch als Text-Trenner auffasst.

Aber ich glaub ich werd in Zukunft eh kaum mehr groupen, denn grad habich .ToLookup entdeckt:


         { // ToLookup() als Alternative zum GroupBy: Ein Lookup ist gleichzeitig auch ein Dictionary der Groups
            var result = products.ToLookup(p => p.CategoryId);
            var x = result[4];
            var result2 = from p in products group p by p.CategoryId into g select g;
            var result3 = products.GroupBy(p => p.CategoryId);
            var arr = result.ToArray();
            arr  = result2.ToArray();
            arr  = result3.ToArray();
         }

syntax-Identisch mit GroupBy(), und auch die Ergebnismenge ist dieselbe (sieht man daran, dass aller dreier Datentyp nach ToArray an dieselbe variable zugewiesen werden kann.
Ein Lookup ist aber zusätzlich gleichzeitig auch sowas wie ein Dictionary, wo man die Groups also nicht nur enumerieren kann, sondern auch per Key zugreifen.
Ein Unterschied besteht ausserdem darin, dass Lookup bereits evaluiert ist - ist mir meist sogar erwünscht.


Jo das Wiki nicht wirklich eine Coder-Resource ist, sah und seh ich auch so. Aber die anderen Beschreibungen
(v.a. Join, Group Join, Left Outer Join, inkl DefaultIfEmpty) fand ich sehr gut und auch bestätigt. Das hat mich denken machen, die wüssten, wovon sie reden 😉

31.03.2016 - 23:19 Uhr

Hi! Ich studiere grade Wikipedia - Linq: LINQ

Alles ok, ausser was da zu Group steht. Dieses meine Testklasse:


   public class Employee {
      public string Name; public int Department; public int Age;
   }

Und wenn ich nun den Wiki-Code bei mir einkopiere, kompiliert das nicht:


      public void Test() {
         var Employees = new List<Employee>();
         var groupedEmployees = 
            from e in Employees
            group e by e.Department 
            group e by e.Age
            select e;

         var groupedEmployees2 = 
            from e in Employees
            group e by new { e.Department , e.Age } 
            select e;

Oder hab ich iwas falsch übernommen von denen?
In meinen Versuchen scheint beim Groupen ein into-Abschnitt obligatorisch.
Und die 2-dimensionale Gruppierung (groupedEmployees) bekomme ich ühaupt nicht gebacken 🙁

(naja - kaum hingeschrieben finde ich doch was):


         var groupedEmployees = 
            from e in Employees
            group e by e.Department into x
            from y in x group y by y.Age into z
            select z;

Edit: (und getestet, und es ist Blödsinn)

31.03.2016 - 16:57 Uhr

Jepp - so müssen Binding-Fehler gemeldet werden - unleserlich, kaum zu verstehen - aber was anderes steht nicht zur Verfügung.
Immerhin siehst du, dass bei deim Werk noch einiges im Argen liegt.

zum anderen Problem:

Ja, das versteh ich auch nicht, was du da machst.
Zumindest den Text kannst du doch ganz normal setzen, denke ich.

Das mit dem grün - soll das eine AttachedProperty werden?
Hab ich grad nicht parat, aber das muss man entsprechend registrieren, und dann auch korrekt abrufen.

31.03.2016 - 16:43 Uhr

ja, ich weiß auch nicht, was die sich bei MS denken.
Ich tät empfehlen, dass du mal in den Optionen einstellst, dass dein Outputfenster wirklich nur Debug-Meldungen outputtet, und nicht das ganze Gefasel da, was du da hast - da findet ja niemand nichts.

Jdfs. da scheint was faul zu sein.

Übrigens VS2012 hat oft die Eigenart, dass Fehler nicht wirklich mit einem Codestop behandelt werden.

Weißt du was ich meine?
Man kann das iwie umstellen, aber hab vergessn wie.

Guck, ein Fehler mit Codestop muss in 2012 so aussehen:

31.03.2016 - 16:16 Uhr

nö - die meldungen kamen schon in 2010.

Du kannst mal ein Binding bewusst falsch setzen, um zu überprüfen, ob du überhaupt BindingMismatch-Feedback bekommst, (und wo - das Ausgabefenster muss man nämlich auch erstmal suchen)

Schmeiss einfach folgenden Unfug ins Grid:

<TextBlock Text="{Binding UffUff}"/>

Das muss einen Fehler ins Ausgabefenster loggen.
Ansonsten musste das Ausgabefenster suchen oder sonstwie zusehen, dass dir dieses Feedback zuteil wird.

@Stu42: Stimmt auch - TemplateBinding ist an dieser Stelle falsch - ist ja kein ControlTemplate.

31.03.2016 - 15:45 Uhr

ich denke, die Bindings stimmen nicht.
Erscheinen da keine Binding-Mismatch-Meldungen im Output-Fenster, wenn du das startest?

30.03.2016 - 18:00 Uhr

und nun geh nochmal dem in Post#2 gesagten gründlich nach.
Die ganze Xml-Wurstelei ist nämlich überflüssig, wenn das dort gesagte zutrifft, und man sich einfach einen Satz Xml-Serialisierbarer Klassen generieren lassen kann.
Und wenn dem so ist, ist das rückspeicher-Problem damit auch abgehandelt - Serialisierung ist bidirektional.

30.03.2016 - 15:57 Uhr

deiner Tutorials ... oft dasitze und denke "ja, schon - aber wieso der Aufwand?" nanu?
also das müssteste mir mal an eim konkreten Beispiel zeigen, in welchem Tut ich einen überdimensionierten Aufwand treibe, und dasselbe Ziel liesse sich einfacher erreichen.

Normal leg ich nämlich größten Wert darauf, nur den geringstmöglichen Aufwand zu treiben.

aber vlt. PM - ist hier wohl recht OffTopic - den TE scheinen meine Tuts ja nicht zu interessieren

30.03.2016 - 13:58 Uhr

Natürlich gibt es ungebundene Spalten. Kannste im Designer gucken: beim Dgv-Spalte zufügen kann man gebundene oder ungebundene zufügen.

Was du gecodet hast als Databinding zu bezeichnen, finde ich verwässert den Begriff - ich würde gerne deutlicher zwischen event-handling und Databinding unterscheiden, auch wenn intern Databinding-Objekte mit bestimmten Events arbeiten.

Wie mans nun macht: binding- oder event-orientiert, da stimme ich dir zu:

Beide Sichtweisen sind natürlich legitim und gut begründbar. Wobei ich zufüge: Kommt auch (glaub sogar: vor allem) auf den Anwendungsfall an.

30.03.2016 - 12:08 Uhr

Also ich stiere jetzt auf dein Code, und ist tatsächlich ein neuer Ansatz, und abseits meiner Denkweise. 👍

Verstehe ich das richtig, dass du das DGV zwar bindest, aber ohne gebundene Spalten - was ja variabel viele Properties erfordern würde.
Stattdessen generierst du ungebundene Spalten und kümmerst dich dann selbst, im CellFormatting, um die Darstellung der Zell-Inhalte.

Tatsächlich ein sehr interessanter Ansatz.

Glaub auch garnet auf aggegierte readonly-Daten beschränkt.
Prinzipiell könnte man ja auch das CellParsing verarbeiten und nutzen, um Eingaben auch wieder zurückzuschreiben.


Edit: meine Sicht "es hat ein typisiertes Dataset zu sein, sonst ist es kein Binding"
Ich hab doch nirgends auch nur entfernt was ähnliches geäussert.
Und es wäre ja auch inhaltlich vollkommener Quatsch.

Ich arbeite viel und gerne mit typDataset, und hab gute Gründe dafür, aber andere, als das was du da scheints falsch verstanden hast.

30.03.2016 - 10:29 Uhr

nö - kein Sarkasmus, oder nur minimal. Nur diese c#6-Neuschreibe kannte ich noch nicht, und ist auch die erste Neuschreibe, die ich kennen lerne, die keinerlei Vorzug hat gegenüber c#5. Aber Peanuts.
/OT
DatenAggregation mit Strukturverlust - gutes Stichwort.
Ja, von derlei Aggrationen halte ich nicht viel, weil kann man nicht rückspeichern. Würde ich jetzt nicht dogmatisch nennen, ein Dogma ist ja eine unbegründete Forderung - meine Abneigung ist ja begründet:
Grundsätzlich bevorzuge ich, in einer Datenverarbeitung zumindest die Option zu behalten, rückzuspeichern.

Aber auch das egal.
Mein Punkt ist, Linq kann prinzipiell keine Ergebnisse erzeugen, deren Objekte variabel viele Properties aufweisen - das ist die Crux mit der Kreuztabelle.
Also muss man so oder so in komplizierten Schleifen eine dynamische Tabelle schaffen.
Linq kann allenfalls Daten dafür heranschaffen.
Das müssen aber mehrere Linq-Queries werden, sodass ein lokales strukturiertes Datenmodell entsteht, aus anonymen Typen womöglich.
Und die komplizierten Schleifen bleiben nachwievor erforderlich, in irgendeiner Weise, um das in beide Dimensionen aufspannen zu können.

30.03.2016 - 02:53 Uhr

Es gibt 2 OleDb-Treiber, einmal ACE-OleDb, und einmal Jet-OleDb.

Normalerweise ist der neuere, bessere installiert, das ist ACE-OleDb.

Such mal auf ConnectionString.Com nach der korrekten Connection-string-Formulierung.

29.03.2016 - 19:00 Uhr

ah - dann ist

public string Name { get; set; };

wohl ein c#6 - Feature, in c#5 musste ich das letzte ; entfernen.


Aber wie gesagt: imo bringt das nix, um der Logik einer Kreuztabelle gerecht zu werden:

Eine Kreuztabelle benötigt 3 Eingabe-Listen, denn sie stellt eine m:n-Relation dar:
1.ZeilenDefinitionen 1.SpaltenDefinitionen 1.Zuordnungs-Tabelle - die Zuordnungen sind dann in die Zellen einzuordnen

Sollen die Zuordnungen selbst auch wieder aus einem Datenbestand ausgewählt werden (Comboboxen), so brauchts dafür logischerweise noch eine 4. Eingabe-Liste.
Nochmal konkret aufs Beispiel bezogen - Man braucht die 4 Eingabelisten (zB Tabellen):
Person, Datum, AnwesenheitsStatus, Zuordnung

Und die Relationen müssen so aussehen:
Person->Zuordnung
Datum->Zuordnung
AnwesenheitsStatus->Zuordnung

Das wäre das erforderliche Datenmodell, wie ich das sehe.
Dann kann man eine TabellenAnsicht erzeugen, wo jede Zelle eine Person, ein Datum und einen Anwesenheitsstatus einander zuordnet.
Dabei werden dann Person und Datum via Zeile/Spalte zugeordnet, und AnwesenheitsStatus als Combobox.

Nu weiß ich garnet, ob der Mantus überhaupt ein typisiertes und relational strukturiertes Datenmodell hat in seiner Anwendung.


edit: nochmal code geguckt, @Mantus: Nein, du hast wohl kein relationales Datenmodell im Client.

Dann würde ich vorschlagen, du arbeitest dich erstmal ganz von vorne ein in Datenmodellierung, Databinding und typisiertes Dataset.
Halte ich für eine Vorraussetzung, um dieses recht knifflige Problem überhaupt sauber lösen zu können.
(klar, evtl. kann man doch noch iwas wursteln, aber ich denk, das wird extrem undurchsichtig und anfällig ausfallen)
Ausserdem gewinnt deine gesamte übrige Anwendung ungeheuerlich dabei, wenn sie auf databinding-getrieben "umgetopft" wird.

Habich Tut zu verzapft: http://www.codeproject.com/Articles/1030969/Relational-Datamodel

  • 2 folge-Artikel dazu.
29.03.2016 - 15:14 Uhr

nach langem drüber nachdenken komme ich zur Vermutung, dass das entweder ühaupt nicht funzt, oder ich steh sehr auf der Leitung.

Zum einen kompiliert das garnet, zum andern kannste glaub noch so viel gruppieren - davon entstehen auch keine Datensätze mit variabel vielen Properties.
Aber ohne variabel viele Properties kommt man wohl kaum zu einen gebunden Grid mitt variabel vielen Spalten.
(Das Combobox-Problem ist davon noch nichtmal berührt.)

Vlt erklärste nochmal, langsam, und für Trottel wie mich nachvollziehbar, was nun dein Ansatz ist?

29.03.2016 - 11:05 Uhr

Naja, das ist schon eine Kreuztabelle.

Je nachdem, wieviele Tage die Suche erbringt wird es verschieden viele Spalten geben.
Und das hat tatsächlich was mit Zeilen/Spalten-Inversion zu tun. Denn die Zeit-Daten werden als Tabelle geliefert, also die Zeilen stehen untereinander in einer Spalte.
Und das muss umgeformt werden, dass sie nun nebeneinander stehen in einer Zeile.

Also im Grunde ist eine Kreuztabelle eine eingeschränkte Darstellung einer m:n-Relation, und da fürchte ich, dass der TE gar kein geeignetes Datenmodell dafür hat.

Weil wo eine Kreuztabelle schon m:n präsentiert, präsentiert eine KT mit ComboColumns noch eine 3. Datenquelle, also der View präsentiert eine m:n:o - Relation.

Edit:
ok, nochmal geguckt: die ZeitDaten werden garnet abgerufen, die werden wohl generiert werden. Was für die Kreuz-Tabellen-Theorie eiglich keinen Unterschied macht - eine Seite der Relation - die Tage - muss horizontal dargestellt werden.

Aber wenn du sagst, das sei kein Problem, dann sag doch auch, wies geht.

29.03.2016 - 10:10 Uhr

ich weiß nicht, welchen aufbau du hier hast.
Und eine Kreuztabelle hat nicht unbedingt was mit Spalten als Comboboxen formatieren zu tun.

Ich weiß nichtmal, was du mit "als Comboboxen formatieren" meinst: In Excel gibts ja oft Comboboxen in den Spaltenköpfen, aber in WinForms versteht man unter ComboboxDatagridviewColumn eine Spalte, die lauter Combos enthält.

29.03.2016 - 09:40 Uhr

ich weiß nicht, was eine Pivot-Tabelle ist.

Ist das, was ich als "Kreuztabelle" kenne?

Für Kreuztabelle habich neulich eine Lösung gebastelt, ist aber sehr kompliziert.

28.03.2016 - 21:44 Uhr

Also ist sozusagen ein "richtiger" aber umständlicher Weg das ich die original Liste der Modelle immer "umpacke" in eine Liste von ViewModellen? Ergibt sich doch logisch zwingend, oder?
Und mit umpacken ist nicht getan, sondern wenn du aus einer ViewmodelListe was löschst, musses auch aus der Model-Liste verschwinden.
Und zufügen nochmal das Theater.
Also wenn der User eine PersonView offen hat, und da ein Haus weghaut, dann muss im Viewmodel die PersonViewmodel-Liste das PersonViewmodel entfernen, und dann auch die PersonModel-Liste aufsuchen, und da die Person auch rauslöschen.

Wie angedeutet - da muss man wohl eine DoubletteObservableCollection<TViewmodel, TModel> erschaffen, evtl. von ObservableCollection<TViewmodel> geerbt, intern einen Verweis auf die Model-Liste enthaltend, und dann muss CollectionChanged abonniert sein, und schön aufpassen, dass die Daten immer synchron bleiben.

Aber tu dich doch mit Bezi aussm annern Thread zusammen, der sollte das doch inzwischen gelöst haben.

28.03.2016 - 20:42 Uhr

Im Prinzip hast Du dann aber trotzdem noch das Model - es liegt eben in dem ViewModel. Nenn es wie du willst - in meiner Begrifflichkeit wäre das Unfug. Ich spreche von Model und Viewmodel nur, wenn es auch 2 verschiedene Klassen sind. Ist es nur eine muss ich ein Wort benutzen, entweder Viewmodel oder Model, oder eiglich ein neues Wort müsste gefunden werden, vlt. "Supermodel"?

Die Logik kann auch im Model (oder Business-Layer) liegen und wird vom ViewModel nur noch genutzt.

Aber dann behandelt das Viewmodel dieselbe Logik doch bereits ein zweites Mal.

Also wenn ich im Model validiere, dass die Person über 18 ist, dann muss ich im Viewmodel validieren, ob im Model validiert wurde, ob die Person über 18 ist.

Und damit ist zweimal sich mit diesem läppischen Thema beschäftigt worden - das meine ich.

Und bitte jetzt nicht in andere Schichten, UnitTests, Sterne und die Unterwelt ausgreifen, das hatte ich schon im anderen Thread.
Da war das Model am Ende auch kein BusinessLayer mehr, sondern war Präsentationsschicht, und blabla und hastenichtgesehen und vollständiger Nebel.

Business-Objekt <-> WCF Service <-> Rep. mit WCF Client -> DTO <-> Model <-> ViewModel <-> View

Darunter tuns die Leute ja nicht.

28.03.2016 - 19:01 Uhr

Auch auf die Gefahr hin, meinen Vorredner zu wiederholen

Frage 1: Ist es richtig das schon Logik in den Models abgearbeitet wird? Also z.B. Das beim hinzufügen eines Haus schon geprüft wird ob die Person über 18 ist? Sowas muss doch nicht ins ViewModel oder? Wenn es angezeigt werden soll, muss es ins Viewmodel.
Und ein User wird wohl angezeigt bekommen müssen, wenn eine seiner Aktionen scheitert.
Eine Möglichkeit wäre, eine Exception zu werfen. Auf jeden Fall muss das Viewmodel sich ebenfalls mit Fehleingaben auseinandersetzen - so oder so.
Frage 2: Wenn beim Setzen der FavColor einer Person alle Farben der Häuser die er besitzt geändert werden soll (Häuser werden in Lieblingsfarbe gestrichen) kann doch so ein Funktionsaufruf auch im Model bleiben und muss nicht im ViewModel als Logik abgehandelt werden. Selbe Antwort: Wenn es angezeigt werden soll, muss es ins Viewmodel.
Frage 3: jetzt ist ja in der Personenklasse schon direkt eine Liste des HouseModels vorhanden.
Wie bekomme ich aber die darin gespeicherten Häuser in ein HouseViewModel damit diese auch für den View aufgearbetiet werden.
Soll die Personenklasse keine Liste von House sondern von HouseViewModel halten? Die PersonKlasse darf keine Liste von HouseViewmodel halten, da würdest du ja die Ebenen vermischen.
Das mit den Listen ist der ganz leidige Punkt an MVVM: Nimmt man die 3-Teilung "M V VM" ernst, so folgt daraus zwangsläufig, dass sowohl in PersonViewmodel eine Liste von HouseViewmodels gehalten werden muss, als auch in PersonModel eine Liste von HouseModels.
Und es ist ein lausiges Problem, diese doppelte Listenführung konsistent zu halten.

Kannst dir auch mal diesen Thread angucken: Eine Listview verschiedene ViewModel WPF<-> MVVM - Teil/Frage2
Aus meiner Sicht, was dem Frager das Problem macht, und ihn sich ans Forum wenden lässt ist eben dieses doppelte Listenführungs-Problem.
Er bringt dann auch ein tolles MVVM-Code-Sample von einem Professor an - bestimmt 3000 Zeilen Code - es lohnt sich, das downzuloaden!.
Aber wenn mans dann auf die Listen-Haltung hin anguckt stellt man fest, dass der Professor sich um das Problem herummogelt, indem er dem Model gar keine Listen zugesteht, sondern die Listen ausschließlich im Viewmodel hält.

Ich finde das bischen geschummelt, denn so ein Model modelliert nur noch unvollständig, also ohne Hinzuziehung des Viewmodels ist das modellierte Spiel (4-Gewinnt) im Model nicht korrekt abgebildet.

Ich mogel an dem Punkt auch gerne, bei mir gibts oft überhaupt keine Models, sondern nur Viewmodels.
Weil das ist mir meist zu dumm, jegliche Logik 2-fach anzulegen - da kann die Logik im Model dann ja entfallen. Was soll ich im Model groß validieren, wenn ich im Viewmodel dasselbe Problem nochmal anfassen muss? - Das kann kein guter Stil sein.
Und dadurch, dasses entfällt wird das Model dann so dumm (Poco nennt man das glaub), dass ich gar keinen Sinn mehr darin sehe, dafür überhaupt noch Klassen anzulegen.
Womit ich die 3-schichtigkeit nicht grundsätzlich ablehne: In manchen Fällen ist es auch sinnvoll, das Model aus dem Viewmodel auszugliedern.

Und hier widerspreche ich jetzt Paladin007, der MVVM prinzipiell als einen aufwändigen Pattern findet:
Also wenn ich Viewmodels ohne Model darunter anlege, dann ist der Pattern super-einfach.
Aber es ist halt nicht die reine Lehre, wie sie in hunderten von Büchern, Artikeln, und auch beim Professor propagiert wird.

Für die reine Lehre muss wirklich jede Model-Logik, die irgendwie im View sichtbar wird, im Viewmodel ein zwietes Mal behandelt werden.
Und mit den Listen ists besonders arg, und ist eigentlich erstaunlich, dass es diese selbst-synchronisierenden Doppel-Listen, wie Paladin007 sie andeutet, dasses diese nicht schon gibt, auf GitHub oderso.

27.03.2016 - 08:41 Uhr

mir ist die komische Syntax recht unbekannt, mit N'Select und

',N'@p0 int,@p1 date,@p2 date',@p0=2,@p1='2016-02-21',@p2='2016-03-22'

Aber ansonsten scheint mir da ein Riesen-Unterschied, nämlich die 2. Query hat einen eingeschachtelten SubSelect - ich täte vermuten, das ist Ursache schlechter Performance.

Ist das iwie besonderes EF-Sql?

25.03.2016 - 14:24 Uhr

jo, paar Beispiele fändich sinnvoll.

Also man kann doch vmtl. Linq-Ausdrücke hinschreiben, und dann dazu loggen, was EF daraus macht und an die DB abesetzt.

25.03.2016 - 06:36 Uhr

Du siehst, es ist sehr schwierig.
Dabei ist das Locken von Datensätzen vlt. noch das einfachste, aber die Anwendung muss auch damit umgehen können, dass Datensätze u.U. auch gesperrt sind, bzw. zwischenzeitlich ihren Sperr-Zustand ändern.
Und auch der BenutzerKomfort leidet darunter, weil bei lockablen Daten muss man immer einen Extra-Edit-Modus betreten und verlassen, und in diesem Edit-Modus ist auch immer nur ein einzelner Datensatz zugreifbar (oder zumindest nur ganz wenige).
Und natürlich grundsätzlich unerfreulich für den User, wenn er Bescheid kriegt, dasser den gewünschten DS grad nicht bearbeiten kann.

Nach der einfachsten Lösung sollte man daher auch immer Ausschau halten, nämlich ob man iwie hinkriegt, dem User nur Daten zu präsentieren, die im Lockstate unveränderlich sind.
Also entweder grundsätzlich gelockt, wo er eh kein Speicher-Recht hat, oder "seine eigenen" Daten, mit denen er machen darf was wolle.

24.03.2016 - 14:05 Uhr

Übungen zum Layout-System in WinForms

Databinding-Tut, darauf aufbauend auch viel DGV-Gestaltung
der erste und der letzte Film zeigt keine Form-Designer-Arbeit.
Die Filme sind auch etwas speziell, weil der FormDesigner ist ja eiglich nicht Thema des Tuts.
Man kann auch bei ungebundenen DGVs die Spalten bearbeiten.

24.03.2016 - 13:56 Uhr

Ich habe noch nie manuell Sachen im Designer hinzugefügt, also wäre es Neuland für mich. Uih - das Neuland lohnt sich aber mal zu betreten!

Das ist auch wohl der Standard, wie man WinForms entwirft, und Standard-Vorgehensweisen sind schon allein deshalb vorteilhaft, weil man leichter drüber reden kann (ma abgesehen von der in diesem Falle wohl millionenfachen Erprobung).

Ich kann mir auch kaum vorstellen, dass du das nicht kennst. Also wenn man seim Projekt auch nur ein Form hinzufügt, kriegt man doch bereits den Form-Designer hingestellt - den klickst du dann immer gleich weg?

Willste paar Videos gugge, zu besonders schnuckligen Problemchen habich hier und da Vids verfasst - insbes. Thema Control-Layout und DataGridview einrichten könnte interessant sein.

24.03.2016 - 11:05 Uhr

ich hätts lieber, du würdest Bildchen hier direkt anhängen.
Auf so Schmuddelhoster geh ich nicht.

an deim Code fällt mir auf, dasses zwar eine CheckboxColumn ist, aber nirgends wird sie einem DGV zugefügt.

Vor allem sollte man sowas im Form-Designer machen, der macht das richtig, und wysiwyg, und das hält den Codebereich auch für wichtigeres frei - my 5 ct.

24.03.2016 - 10:27 Uhr

Guck dir unbedingt an, was ein typisiertes Dataset ist, wie man es mit DataAdaptern befüllt, und wie man damit Views gestaltet.

Diese Technologie heißt "Databinding", und ist nicht nur maximal unterstützt, sondern stellt gleichzeitig eine fabelhafte Möglichkeit dar, eine tragfähigere Architektur umzusetzen, mit Trennung von Daten und Oberfläche.

ein klein Einblick siehst du hier in Videos: http://www.vb-paradise.de/index.php/Thread/94955-die-vier-views-auf-video/#post798777

Eine aufbauende Artikelserie aus 3 Teilen hier: http://www.codeproject.com/Articles/1030969/Relational-Datamodel

Beachte, dass ich zum Datenbank-Zugriff kaum was sage. Nur soviel: Dem Dataset ists egal, wie mans befüllt, das einfachste ist sogar, es ohne Db direkt von Platte zu laden.

Letzteres empfehle ich sogar sehr, nämlich Neuanwendungen erstmal prototypisch fertig-zu-entwickeln, und erst zum Schluss eine richtige DB hinterlegen.

Da ist man bei Änderungen des Datenmodells (solch bleibt nie aus) wesentlich flexibler.
Des weiteren kann man Backups erstellen, die die "Datenbank" mit beinhalten.
Sonst ist ein Backup ja nur Müll, wenn zwischenzeitlich die Db weiterentwickelt wurde.

21.03.2016 - 13:02 Uhr

ist ja eigenartig.
Bei mir muss ich immer auf die Checkbox klicken, dass die sich ändert.
Klicke ich ine eine andere Zeile oder Spalte, bleibt sie völlig ungerührt.

20.03.2016 - 13:00 Uhr

Prima!

Dann ist ja alles geklärt 👍 🙂

20.03.2016 - 10:58 Uhr

Klasse Autoliste_ViewModel --> was mache ich hier ??? Autoliste oder List<BaseViewModel> Natürlich letzteres.
Und im View dann DataTemplates einsetzen für die verschiedenen SpezialTypen - wenn diese denn überhaupt spezifische Templates benötigen.

Weil grundsätzlich sind Autos ja einander sehr ähnlich, da würde es reichen, auf einen bestimmten Hersteller zu verweisen, und damit wäre abgegessen, obs ein Mercedes ist oder BMW.

20.03.2016 - 09:52 Uhr

Das scheint Absicht zu sein, weil er keine 2 parallelen Listen haben will.
Deshalb gibt es nur eine SpielerVM-Liste im Viewmodel, aber keine Spieler-Liste im Model.
Ob das "richtig" ist, lasse ich mal dahingestellt sein - scheinbar kann man das Realitäts-Faktum, dass es 2 Spieler gibt, im Model weglassen, im Viewmodel dann aber wieder nicht.

Jdfs. ist mir dieses Kernproblem der Model-Segregation im MVVM-Patterns schon öfter begegnet:
Ein Model braucht evtl. Listen von Sub-Models, um seine Realität richtig zu modellieren.
Und ein Viewmodel braucht Listen von Sub-Viewmodels, um das View richtig zu modellieren.
Da die Sub-Viewmodels Wrapper von Sub-Models sind, entsteht an diesem Punkt eine sehr problematische redundante Datenhaltung.

Wie gesagt: Für dein Problem der parallelen Listenhaltung gibt weder 4-Gewinnt noch TicTacToe wirklich was her, denn beide Spiele haben sowas garnet.
Bzw. nur in ganz starrer Form, also es gibt 2 Spieler und basta.
Und initial werden Plätze angelegt, aber während des Spielverlaufs passiert da ja nix.


Edit: Hihi - guckmal, was ich grad in Core fund:

   public class Spiel {
      private readonly Spielbrett _spielbrett;
      private readonly IReadOnlyList<Spieler> _spielerListe;

      public void StarteSpiel() {
         throw new NotImplementedException();
      }
   }

Also sieht mir aus, als habe er anfänglich durchaus daran gedacht, eine SpielerListe auch im Model zu führen, aber später wieder verworfen, und dann vergessen, die Spiel-Klasse zu löschen.

20.03.2016 - 00:17 Uhr

Hihi - das ist, was ich am MVVM so liebe: Er ist recht klar definiert.
Diese 3 - Schichten-Geschichte scheint mir (ähnlich wie MVC, MVP) auch annähernd so viele Auslegungen zuzulassen, wie es Programmierer gibt.
Aber meinetwegen - MVVM bewege sich halt nur in der Präsentations-Schicht.

Aber vlt. solltem man auch nochmal auf Bezis Frage zurückzukommen:

Kann ihm jemand sagen, was in die ElementListe gehört, und was in die ViewModel_Elementliste?
Und wie man es richtig implementiert?

19.03.2016 - 19:52 Uhr

Vlt. ist so ersichtlicher:

Business-Objekt <-> WCF Service <-> Rep. mit WCF Client -> DTO <-> Model <-> ViewModel <-> View leider nein.
Von alle dies dolle Dinge sagen mir nur Model, ViewModel und View etwas.
Und warum du <-> dazwischen-setzst ist mir auch unklar.

Aber nochmal zum Zip: Wie kommt das in deine DropBox?
Oder ist das die Dropbox vom Prof?

19.03.2016 - 19:26 Uhr

erstmal vielen dank für das hübsche 4-Gewinnt! 👍
Hast du das gemacht, oder ist das das vom Video?

Und natürlich melde ich gleich mal an, dass es mir unerhört oversized aussieht - also 38 Dateien aufzusetzen, um son popeliges 4-wins zu gestalten - wie gesagt: Ich wäre mit einer popeligen 2-D-Liste von Booleans eingestiegen, und ich glaub, so viel mehr wäre da garnicht hinzugekommen.

Dann bringst du mich mitte Begriffe tatsächlich ganz durcheinander.

Was ist ein Model, ein Business-Model, ein fürs Frontend-erstelltes Model?
Ein Business-Objekt - ist das ein Model oder ein Viewmodel?

19.03.2016 - 17:43 Uhr

Die Logik eines Arrays von List<bool>?

(oder kurz List<bool>[4])

nein, da musst du auch nix re-implementieren, wenn du eine Winforms-Oberfläche, Konsole oder sonstwas drauf ausetzen willst.

List<bool>[4] - da steckt schon eine Menge Logik drinne, imo fast ausreichend, um ein 4-gewinnt zu modellieren.
Hinzu käme noch ein Toggle-bool der sagt, welcher Spieler dran ist, und dann noch Logik, die testet, ob einer gewonnen hat.

Hier, ich hab mal ein TicTacToe gebastelt - ist ja von 4-Gewinnt nicht soo verschieden:
https://www.vb-paradise.de/index.php/Thread/92049-TicTacToe/

Aber ist wieder son Fall, wo ich Model und Viewmodel zu trennen zu faul bin.
Also ein Model könnte man da heraus-seggregieren als ein bool?[9] - also 9 nullable booleans, die aussagen, ob und von wem eine Zelle gesetzt ist.

Aber bringt alles nicht viel zu deim ich finde wirklich kniffligen Problem:
Nämlich du hast Listen von Model-Klassen und Listen von Viewmodel-Klassen.
Und weil du das hast, musst du Sorge tragen, dass diese Listen auch wirklich konsistent bleiben.

Weder 4-Gewinnt noch TicTacToe haben diese Problematik.

19.03.2016 - 17:14 Uhr

Hmm - kann man irgendwo des Codes habhaftig werden?
Ich mag da jetzt nicht stundenlang utube gucken, und versuchen, seine Solution vom Bildschirm abzuschreiben.

Ich hab das jetzt auch nicht verfolgt, was er im Einzelnen macht, um "Spielstein in Spalte fallenzulassen".
Vom Modell her sollte das nichts weiter sein, als dass einer Spielstein-Auflistung (nämlich der Spalte) ein Spielstein hinzugefügt wird.
Im Minimal-Modell würde als Spielstein sogar ein einfacher Boolean reichen, für schwarz oder weiss.

Also nochmal: das Model eines Vier-Gewinnt-Spiels braucht nicht mehr zu sein als ein Array mit 4 List<bool>

Alles annere wäre Viewmodel.

Naja, so jetzt aus dem Bauch heraus.

Kann man sein Werk iwo downloaden?

19.03.2016 - 15:43 Uhr

Das liegt meiner Meinung daran, dass bei diesem abstrakten Entwurfsmuster die Begrifflichkeiten in der Praxies verschwimmen können und auch von dem einen oder anderen anders aufgefasst werden können. Einspruch!
Also ich find die Begrifflichkeiten bei MVVM wohltuend klar, und da verschwimmt auch nix.
Wenn ich da an MVP oder MVC denke - das war ja vlt. ein herum-rudern!

Aber bei Model, View, Viewmodel kann man für jedes Stückerl Code zeigen und begründen, wo's hingehört, und warum.

Ansonsten sehe ich die Unterteilung exakt so, wie von dir beschrieben, also nix mit "kann jeder sehen, wie wolle".

Leider geht beim verlinkten Sample der Download-Link nicht, und die im Blog eingesprenkelten Code-Snippets und Bildle sind ja nur "Versprechungen", die dann der Download halten müsste.

19.03.2016 - 14:19 Uhr

ich find, du fasst überhaupt nicht auf, was ich sage.
Nirgends lehne ich den MVVM ab.

Auisserdem gebe ich dir doch auch eine Richtschnur, in genau deinem Sinne:

Aktionen deiner Anwendung dürfen ausschliesslich nur übers Viewmodel laufen.
Sobald du am Viewmodel vorbei iwas am Model rumfummelst, können inkonsistente Zustände entstehen, Scherze wie dass im Model etwas anders einsortiert ist als im Viewmodel usw... Wie kannst du das übersehen, wo ichs extra eingerahmt habe?
Diese Richtschnur macht ja überhaupt nur Sinn unter Vorraussetzung einer Trennung von Model und Viewmodel, also folgt ganz genau dem, was du bisher mit MVVM mitbekommen hast.

Aber ich kann auch weiter auf konkrete Einzelfragen eingehen - prinzipiellere Betrachtungen scheinen ja iwie problematisch. Also du frugst

Was gehört nun in mein ViewModel_Elementliste? Erzeuge ich hier ein Objekt von meiner Klasse Elementlist oder eine Liste von ViewModelBase.
Für was bräuchte ich dann suchfunktionen im Core ? Wie füge ich elemente meiner Liste (Elementliste oder List<ViewModelBase>) hinzu ? Ja, in ViewModel_Elementliste muss ein Objekt von Model_Elementliste enthalten sein.
Ob du es nun injizierst oder ob du es selbst erstellen lässt - Profis werden jetzt vermutlich mit einem DI-Framework kommen zum injizieren.
Ja, und eingefügt werden nur Viewmodel-Elemente - ganz getreu obiger Richtlinie. Das ViewModel_Elementliste muss dann einen eigenen Mechanismus haben, dementsprechend der (im ViewModel_Elementliste enthaltenen) Model_Elementliste auch was zuzufügen.
Mit entfernen dito, parallele Listenhaltung eben.

Auch hier ist wieder offen, wie du in die zugefügten Viewmodels die Models reinkriegst.
Jedenfalls wenn deine Viewmodel einen parameterlosen Konstruktor bereitstellen eröffnet dir das die Option, etwa in einem Datagrid in der ZufügeZeile einen Datensatz zuzufügen.
Wohlgemerkt - nur eine Option - oft ist nicht geraten, das auch zu nutzen, aber die Option zu kennen schadet wohl nicht.

Für was bräuchte ich dann suchfunktionen im Core ? ja, weiß ich auch nicht. IMO brauchst du eine Suchfunktion im Viewmodel (getreu obiger Richtschnur), und nicht im Core.

19.03.2016 - 11:56 Uhr

Etwas rundheraus abzulehnen, weil "Sonst würde etwas (anderes) keinen Sinn machen" - naja, das ist kein Begründen, sondern ist im Kern dogmatisches Denken. Also wo (bei Unvereinbarkeit) die Lehrsätze Vorrang haben vor dem, was sich aus Anschauung der Realitäts ergibt.
Prinzipiell sollte man sich aber imo den Kopf so weit freihalten, dass es tatsächlich auch vorkommen kann, dass etwas keinen Sinn macht - sowas gibts halt inne Realität.

Aber auch sonst ist das Argument ganz unlogisch:
Wieso macht MVVM keinen Sinn, nur weil sich in konkreten Einzelfällen oft genug zeigt, dass die Auftrennung von Viewmodel und Model unpraktikabel ist?
IMO tut das dem MVVM-Pattern garnix. Und es gibt weiterhin noch jede Menge Fälle, wo diese Auftrennung unverzichtbar ist.
In diesen Fällen kann man das begründen, und zwar besser als mit "sonst würde iwas anneres kein Sinn mehr machen".

Ansonsten -

...das man halt alles in kleine Views packt und das solange aufbaut von kleinen einzel Elementen bis zur kompletten View... Ja, seh ich auch so.
Und die Vorgehensweise gilt nicht nur für Views, sondern auch für Viewmodels, und wenn man auch ein Model hat, gilt es auch dafür.

Egal.
Solche Diskutiererei verwäscht nur den Kern, den ich dir mitteilte:

Aktionen deiner Anwendung dürfen ausschliesslich nur übers Viewmodel laufen.
Sobald du am Viewmodel vorbei iwas am Model rumfummelst, können inkonsistente Zustände entstehen, Scherze wie dass im Model etwas anders einsortiert ist als im Viewmodel usw...

Bitte fasse das auf, und probier, ob es als Richtschnur funktioniert.
Und probier gerne auch aus, es iwie anders zu machen, das wäre sogar ausgezeichnet, dann hast du eine Vergleichsmöglichkeit.

Noch toller wäre - allerdings quasi ein Rewrite - du probierst es ganz spasseshalber auch mal ohne Viewmodel/Model - Trennung - nur um zu sehen, wie weit du damit kommst, und ab wann der Ansatz sich dann tatsächlich als unzureichend erweisen wird.

19.03.2016 - 11:01 Uhr

Ich stehe mit dem Viewmodel-Konzept bisserl auf Kriegsfuss.

Weil wenn du eine Viewmodel-Schicht zwischenschiebst, dann darf deine Anwendung in keinem Fall mehr jemals auf eine Model-Klasse zugreifen.

Mit dem Ergebnis, dass die Model-Klasse eiglich garnix mehr zu tun hat.

Wie dem auch sei: Wenn du das so aufziehen willst, merk dir einfach - das ist meine Antwort auf deine Frage: Deine Anwendung darf nur über Viewmodels agieren, nix anners.
Insbesondere Suchen und Löschen und Scherze - muss alles auf den Viewmodels laufen.

Ansonsten müsstest du ja ein mordsmäßiges Benachrichtigungs-System implementieren, und damit versuchen, dass das Viewmodel was empfängt vom Model, und darauf geeignet reagiert.
Das wird ziemlich kompliziert, und evtl. auch nicht immer lösbar, und v.a. wäre es von hinten durch die Brust ins Auge.

Edit:
Ich sehe grade, ja, du steckst mitten drin, und hast bereits doppelte Listen-Führung angefangen, es gibt bei dir Viewmodel-Listen und Element-Listen.
Ja, wird lustig. Wie gesagt: Die Anwendung agiert nur auf dem Viewmodel, und dass muss mw. iwelche Mechanismen haben, dass das Model ständig nachgeführt wird.

Wie gesagt: versuche nicht andersrum, das Viewmodel dem Model nachzuführen, oder gar Mixturen davon.

17.03.2016 - 15:29 Uhr

normalerweise sollte das Gui die Bindings über WeakEvents empfangen, und so MemoriyLeaks vermeiden.

google mal Stichwort "IWeakEventListener"

17.03.2016 - 15:20 Uhr

Hups - das ist ja ein ziemlich reiichhaltiger View auf einmal!

naja, da würde ich entweder das telrik-Produkt kaufen, oder individuell den View so hinbasteln, dasser passt. Das wäre dann nicht so allgemein verwendbar wie vmtl. das telrik-Grid, aber leistbar.
Ich würde aber wohl nicht versuchen, dieses Monster-Control nachzuprogrammieren.

17.03.2016 - 14:56 Uhr

nee, kenn ich nicht.

17.03.2016 - 14:41 Uhr

usercontrol ist was anderes als ein CustomControl.

ucl findich ganz einfach - damit bildet man quasi Teil-Xamlse, wenns im Window zu voll wird.

CustomControl weiß ich grad garnet. achja, ich hab mal eine AutoCompletion-Textbox gebastelt, bei der ich das Selections-Verhalten stark verändert habe, damit man immer einen eindeutigen "Append-Suggestion"-Bereich hat.

also wirklich ein andersartiges Verhalten, und war mit Behavior oder Events kaum hinzukriegen.

Ansonsten sind die Wpf-Controls unerhört flexibel, und dass man ein CustomControl wirklich braucht höchst selten.

17.03.2016 - 14:18 Uhr

x:Class ist eine Markup-Extension, die bewirkt wohl, dass eine Xaml-Datei als Klassen-Definition des Attribut-Wertes interpretiert wird.
Also

<ResourceDictionary>
   ...

ist ein ResourceDictionary, aber

<ResourceDictionary x:Class="BlaBla">
   ...

ist eine BlaBla-Klassen-Definition, und zwar Blabla erbt von ResourceDictionary.

So reime ich es mir zusammen, nach der richtigen Doku der x:Class-Markup-Extension googelste vlt besser selber.

Zu deim andern Code kann ich kaum was sagen, ich weiß nicht, was der bezwecken soll.

Ich würde auch gar keine ClearTextbox programmieren, das widerspricht dem "Composition over Inheritance"-Prinzip.
Also wenn ich eine Textbox mit Löschen-Button will, dann mach ich einen Löschen-Button hin.
vlt. mach ich sogar ein UserControl, DataTemplate oder ControlTemplate davon, wenn ich sowas öfter bräuchte.
Aber ein Custom-Control würde ich mir deswegen nicht antun.

Aber immerhin scheint er mir ineffizient - egal was er beabsichtigt. Weniger Casts und "String-Smells" hätteste wohl so:

var tb = GetTemplateChild("innerTextBox") as TextBox;
if(tb != null)tb.TextChanged += InnerTextBox_TextChanged;

(Aber wie gesagt: lieber überhaupt nicht.)

17.03.2016 - 12:55 Uhr

kann iwie nicht sein.
Cleartextbox erbt von Textbox, aber die Text-Property soll beim Erben verschwunden sein?

Ich vermute einen Namenskonflikt, oder eine Abschattierung irgendwo.

edit:
Ah - evtl. isses das:
in deim Generic.Xaml taucht ein x:Class="ClearTextBox" - mach das mal weg, wenn du nicht ganz sicher bist, wozu es gut und notwendig ist.

17.03.2016 - 00:11 Uhr

verstehe ich dein Repository richtig, dass für jede Entity ein eigenes Repository besteht?

ich hab immer gedacht, ein Repository sollte für alle Entities Query-Ergebnisse generieren können.

Aber ich weiß jetzt auch nicht, ob das problematisch ist, für jede Entität ein eigenes Repository zu führen, aber ich glaub fast.
Weil dann muss es ja ein "Super-Repository" geben, was alle Repositories zusammenfasst.

Also für mein Verständnis liegt hier ein Benamungs-Irrtum vor.
Was du Repository nennst schein eher eine Art DataAdapter für eine Entität zu sein.
Und das Repository solte evtl. mehrere solcher Adapter enthalten - je Entität einen.

(also meine 5 ct)