Support, Anregungen, Wünsche zur Tutorialreihe <WPF lernen/>

  • WPF MVVM

Es gibt 448 Antworten in diesem Thema. Der letzte Beitrag () ist von Nofear23m.

    Jeiss schrieb:

    Hab aber mal kurz die Windows Ressourcen auskommentiert

    Schon mal auf OK geklickt? Ich denke wenn die Resourcen auskommentiert sind wird dir VS den Knoten "Window.Resources" NEU erstellen.

    Probiers einfach, ich glaube auch da funzt Undo (STRG + Z).

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Ja stimmt, "Window.Resources" werden NEU erstellt.

    So aber jetzt endlich zu meiner eigentlichen Frage zum Tutorial im Kapitel 2.1.1.2 Templates. Genauer das Projekt
    mit den Autos zum Thema Data Templats. Hab dein Porjekt „reporduziert“. Anderer Projekt-Name und alles
    im Mainwindow (statt im DataTemplate.xaml)
    Was mich verwirrt hat(weil meine Listbox aus einem ganz anderen Grund keine Logos angezeigt hat...) waren die zwei Zeilen im "Kopf" (tut mir leid, weiss aber nicht wie der obere Bereich in jedem XAML-Editor heisst..)

    XML-Quellcode

    1. mc:Ignorable="d"
    2. d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True,Type={x:Type local:DataTemplate}}"

    Mach mir darüber keine Sorgen mehr. Brauch ich in meinem Projekt im Mainwindow irgendwie nicht. Und hab dann ein bisschen über ignorable gegoogelt. Habs nicht ganz verstanden...
    Wenn jemand dazu was "leicht verständliches" sagen könnte...
    Aber was mir viel wichtiger zu sein scheint, ist im Code behind vom DataTemplate Window die kurze Zeile

    VB.NET-Quellcode

    1. Me.DataContext = Me

    Ok geht um den Kontext des ganzen DataTemplate Windows.
    Ich weiss, dass man einem anderen Window den Kontext von Me übergeben kann. Aber Me sich selbst den Kontext übergeben... irgendwie seltsam.

    Jeiss schrieb:

    waren die zwei Zeilen im "Kopf"

    Das oben nennt man Namespaces. Und die Zeile die du gepostet hast ist für den DesignTime Support.
    Einfach damit man zur Designzeit (also im Editor von VS) auch Daten sieht. z.b. kann man dann gut erkennen ob man die Bindings korrekt gesetzt hast. Ausserdem hat man dann Intellisense beim Binden.

    Jeiss schrieb:

    Und hab dann ein bisschen über ignorable gegoogelt. Habs nicht ganz verstanden

    Ne, wenn du das nicht brauchst lass d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True,Type={x:Type local:DataTemplate}}" einfach weg. Besser aber du passtg es an.
    Wenn dein Window MainWindow heisst dann so: d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True,Type={x:Type local:MainWindow}}"

    Aber... hierzu muss man erstmal verstehen wie das ganze funktioniert, das kommt aber in späteren Kapiteln, also ein wenig Geduld.

    Aber was mir viel wichtiger zu sein scheint, ist im Code behind vom DataTemplate Window die kurze Zeile

    Ja, da dieses Beispiel weder MVVM noch ein anderes Pattern verwendet um alle hier einfach zu halten, es geht ja um Templates und nicht um Code, wurde der DatenContext des Windows an sich selbst gebunden.
    Me.DataContext = Me bedeuted. Wenn du im CodeBehind ein Property mit dem Namen "Test123" hast kannst du im XAML mit Text={Binding Test123} binden.

    Hoffe das ist soweit klar.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Ok, hab mal wieder einiges dazu gelernt.
    Für mich war bis jetzt der Namespace in XAML nur die erste Zeile. Also z.b.

    XML-Quellcode

    1. <Window x:Class="MainWindow"

    Und wie du es gerade erklärt hast, reicht das aber bis zur "schließenden" spitzen Klammer. (>) Da meine XAML-Kenntnisse ja auch so schlecht sind... ist für mich ein Namespace sowieso etwas aus der VB.NET-Code Welt. Aber das müsste ich ja recht schnell begreifen, bald hoffe ich...
    Also das mit dem d:DataContext="{d:DesignInstance IsDesignTimeCreatable=True,Type={x:Type local:MainWindow}}" kann ich jetzt bestätigen, dann seh ich auch was zur Design-Zeit in meinem ListBox. Hatte ich auch probiert, brachte aber nix da ich noch ein anderes Problem mit dem Anzeigen der Logos hatte... Ok klappt aber jetzt.
    Aber trotzdem Sascha, sag mir bitte (bestätige) folgendes. Wenn man also selber kein so ein "schlaues Köpfchen" ist. Und auch nicht das Glück hat solche aus einem Forum, oder so zu kennen, dann hilft einem die IDE nicht indem "d:DesignInstance" automatisch hinzugefügt wird. Sondern das muss man sich jedes mal "händisch" (gibt es das Wort in der deutschen Sprache....?) im XAML code hinzufügen. Oder?
    Also das mit Me.DataContext = Me, da hab ich mir schon gedacht dass das eben eine sehr einfache Form der "Datenbindung" ist. Ist aber trotzdem gewöhnungsbedürftig.

    Nofear23m schrieb:

    Me.DataContext = Me bedeuted. Wenn du im CodeBehind ein Property mit dem Namen "Test123" hast kannst du im XAML mit Text={Binding Test123} binden.

    Ok, stimmt. Die ListBox wird im Window an AutoListe gebunden. Und

    VB.NET-Quellcode

    1. Public Property AutoListe As ObservableCollection(Of Auto)
    ist ein Property aus dem Codebehind (obwohl Auto eine schöne, separate Klasse ist), wie es sich gehört. Ok, sogar für mich verständlich...
    Sprengt zwar jetzt den Rahmen, aber falls jemand Zeit und Lust Hätte. Was wäre denn eine "äquivalente" XAML-Variante für eine so "simple" Bindung "à la" Me.DataContext = Me
    Danke

    Jeiss schrieb:

    Für mich war bis jetzt der Namespace in XAML nur die erste Zeile.
    Naja, fast. Alles was in etwa so ist xmlns:xyz="blablabla" is die Angabe eines Namespaces.
    Wie z.b. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" oder eben xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    Und nach Angabe des letzterem kann ich d dann verwenden!! und Habe die Properties aus dem d Namespace wie z.b. d:DesignHeight="300" d:DesignWidth="300"

    Hoffe jetzt wird es klarer.

    Jeiss schrieb:

    Wenn man also selber kein so ein "schlaues Köpfchen" ist. Und auch nicht das Glück hat solche aus einem Forum, oder so zu kennen, dann hilft einem die IDE nicht indem "d:DesignInstance" automatisch hinzugefügt wird. Sondern das muss man sich jedes mal "händisch" (gibt es das Wort in der deutschen Sprache....?) im XAML code hinzufügen. Oder?

    Na, meines Wissens nach kann der Designer das nicht generieren. Manche Dinge muss man Händisch erledigen. 8o

    Jeiss schrieb:

    Was wäre denn eine "äquivalente" XAML-Variante für eine so "simple" Bindung "à la" Me.DataContext = Me

    Ich überlege gerade, ich denke rein in XAML wird das gar nicht gehen. Und kannst an eine Windowklasse erst im Loaded Eventhandler Binden da du sonst lauter Exceptions um die Ohren geworfen bekommst. Aber dafür gibt es andere Möglichkeiten. Bitte denke über diese Art der Bindung jetzt nicht so viel nach. Wie gesagt, schau mal ins Inhaltsverzeichniss, da kommst noch viel.
    Das nächste Tutorial sind z.b. Namespaces. Welch Zufall !!!!
    Deshalb, ein wenig Geduld, dein Kopf wird schon noch genug rauchen!

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Jeiss schrieb:

    Me.DataContext = Me
    Ich würde dir empfehlen, dich damit nicht so viel zu beschäftigen.
    Ein Window mit sich selbst als DataContext führt den MVVM-Pattern (Trennung von Daten und GUI) ad absurdum. @Nofear23m sagt ja selbst, das ist quasi Quick & Dirty, weil MVVM in dem Kapitel nicht das Thema ist.

    Nofear23m schrieb:

    Alles was in etwa so ist xmlns:xyz="blablabla" is die Angabe eines Namespaces.
    Ich würd nicht sagen "So in etwa", sondern genau.
    xmlns: - das ist im Xaml die Deklaration eines Xml-Namespace-Imports. Deswegen heists ja: xmlns
    In Vb schreibste Imports vb6 = Microsoft.VisualBasic, und im Xaml schreibste: xmlns:vb6="clr-namespace:Microsoft.VisualBasic;assembly=System"
    Allerdings ticken Xml-Namespaces klein bischen anders als vb-Namespaces.
    Vielleicht darf ich das kurz versuchen. Dazu möchte ich auch gleich ein wenig vorgreifen. Nähmlich zum MVVM-Model.

    Das MVVM-Pattern besteht ja aus 3 verschiedenen Schichten: Dem View, ViewModel und das Model.

    View ist das was der Nutzer der Applikation sieht. Also alles das, was designertechnisch für die visuelle Darstellung an Möglichkeit besteht, damit der Anwender (und somit das Programm auch selber) braucht, um die typische Trennung von View und ViewModel zu erreichen. Diese erfolgen nähmlich nur durch Bindungen.
    Damit entsprechende Bindung mit ViewModel funktioniert muss View eine Art "Property" haben, die in diesem Fall "DataContext" heisst.

    ViewModel ist ganz einfach ausgedrückt, das Konstrukt oder eben das Model von View. Auf ViewModel wird nur mit Bindungen zugegriffen. Damit die Bindungen, die ja hauptsächlich mittels Properties realisiert werden, den "Datenaustausch" in beide Richtungen auch korrekt umgesetzen, muss eine Möglichkeit bestehen welche die Änderungen auch an View bzw. ViewModel weitergeben. Dafür ist das Change Notification (INotifyPropertyChanged) zuständig.

    Und zu guter Letzt das Model. Model wird immer mit den handfesten Daten in Verbindung gebracht. Also alle Daten die visuell auf dem Bildschirm dargestellt werden sollen. Der Anwender kann die Daten vielfach auch manipulieren, je nachdem um was für eine Applikation es sich auch handelt. Daher muss das Model auch folgende Funktionen umsetze können.
    • Validierung der Daten mittel IDataErrorInfo
    • Benachrichtigung bei Property-Chance INotifyPropertyChanged

    Die Praxis zeigt aber auch, dass es Situationen gibt, wo die Model-Schicht nicht gebarucht wird. Das ist meistens dann der Fall, wenn die Daten mit einem Service in Verbundung gebracht werden.



    Jeiss schrieb:

    Me.DataContext = Me


    In diesem Fall wird genau das Umgesetzt. Es wird also Me (MainWindos-Klasse) an DataContext übergeben.


    Bitte korrigiert mich, wenn ich was Missverstanden habe.


    Freundliche Grüsse

    exc-jdbi
    Hallo

    exc-jdbi schrieb:

    Daher muss das Model auch folgende Funktionen umsetze können.

    Ich nehme an du hast dich vertippt. Du meintest ViewModel oder?

    exc-jdbi schrieb:

    Die Praxis zeigt aber auch, dass es Situationen gibt, wo die Model-Schicht nicht gebarucht wird. Das ist meistens dann der Fall, wenn die Daten mit einem Service in Verbundung gebracht werden.

    Die Praxis zeigt das man eher mehr Schichten benötigt als weniger. Klar, bekomme ich die Daten von einem Webservice kann ich die eigendlich die Model-Schicht weglassen, in der Praxis hat man aber in einer Anwendung irgendwann so viel Logik das das ViewModel augebläht ist und mann macht eine Bussinesslogic dazwischen. Oder je nachdem wie man Daten bekommt sogar vor die Businesslogic noch einen DataAccessLayer.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Guten Morgen Sascha

    Da bezog ich mich schon auf das Model. Ich würde hierbei eine BasisKlasse mit den beiden Funktionen (IDataErrorInfo INotifyPropertyChanged) erstellen. Dann ein Model erstellen und die Basisklasse erben.

    Edit: Es ist aber beides möglich. Change Notification kann man natürlich auch im ViewModel machen. Danke für den Hinweis.



    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    Hallo

    Ich denke du vertauscht hier etwas. Das Model beschreibt deine Datenstruktur.
    Dann hast du dein ViewModel. Das ViewModel gibt die Daten an die View über Binding.
    z.b. hast du im Model "Auto" das Property PS. Im ViewModel willst du das der User sowohl die PS als auch die KW eingeben kann. Je nachdem was er für Daten zu Verfügung hat.
    Gibt der User 73 KW ein wird im View bei PS 100 PS angezeigt. Gespeichert wird auch in PS, weil du hast im Model ja nur ein PS Property.

    Das bedeutet das du KW ja auch validieren musst. Klar kannst du das Model auch Validieren, aber du machst es im viewModel auf jeden Fall auch weil du ja prüfen musst ob korrekte Daten im ViewModel sind bevor du diese ins Model transferierst.
    INotifyPropertyChanged hat im Model keinen Sinn. Warum? Im View werden Eigendschaften den ViewModels angezeigt (Binding). Die WPF muss also benachrichtigt werden wenn sich eine dieser Eigenschaften ändert. Aber es muss nicht Benachrichtigt werden über Eigenschaften aus dem Model, warum auch, das View hat nix mit dem Model direkt zu tun. Ergo muss INotifyPropertyChanged in die Basisklasse des ViewModels.

    Ich versuche immer im Model so wenig Logik wie nur irgendwie möglich drinnen zu haben, aus dem einfachen Grund weil ich genau wissen möchte wo ich Logik zu suchen habe. Habe ich Logik an mehreren verschiedenen Stellen verteilt über mehrere Layer suche ich jedes mal auf neue wo jetzt was gemacht wird. Das Model Beschreibt im Grunde nur dein Datenmodell (wie der Name schon sagt).
    Es gibt sehr viele Ansätze im Model diverse Logik zu implementieren und dort alles mögliche zu unternehmen, bin aber kein Freund davon da ich gerne (wenn ich die Layer schon Trenne) auch meine Logik trenne.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hört sich gut und auch richtig an. Die Logik gehört ins ViewModel.
    Ich bin leider noch nicht ganz soweit, und werde mir das natürlich auch noch anschauen. Bis jetzt habe ich das immer in das Model einfliessen lassen.

    Danke @Nofear23m

    Freundliche Grüsse

    exc-jdbi
    @exc-jdbi ich sage jetzt auch nicht das es völlig Falsch ist. Was ist schon Falsch und was Richtig?

    Hast du sehr wenig Logik und willst es einfach halten, kann es sinn machen da du es im ViewModel einfacher hast.

    Beispiel:
    Ich habe ein Autohaus mit Eigenschaften wie Adresse, Name usw. und auch eine Eigenschaft Autos mit einer Collection(of Auto).
    Auto hat wieder eigenschaften wie Marke, Modell, PS usw.

    Korrekt müsstest du jetzt zwei ViewModel`s machen. Ein AutoHausVm und ein AutoVm.
    AutoHausVm enthält Properties wie Adresse, Name usw. und ein Property Observablecollection(Of AutoVm)
    AutoVm enthält Properties wie Marke, Modell, PS usw.

    Alternativ (wenn man wirklich INotifyPropertyChanged im Model drinnen hat) kann man ja auch NUR mit einem AutohausVM auch auskommen.
    AutoHausVm enthält Properties wie Adresse, Name usw. und ein Property Observablecollection(Of Auto)
    Du sparst dir also das AutoVm. Benötigst aber im View einen Verweis auf das Model und bist bei weitem nicht so flexibel. Du kannst nämlich nur genau die Eigenschaften anzeigen welche im Model enthalten sind, nicht mehr nicht weniger. Musst also dann viel mehr mit Convertern Triggern usw. im View arbeiten.

    Wenn du noch fragen hast frag ruig.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    ums nochmal herauszustreichen: Hast du ein Autohaus mit Autos, so entstehen nach MVVM (in voller Ausbaustufe) 4 Klassen:
    Auto mit Marke, Modell, PS usw.
    Autohaus mit Adresse, Name usw. und auch eine Eigenschaft Autos mit einer Collection(of Auto).
    AutoVM mit Marke, Modell, PS usw.
    AutohausVM mit Adresse, Name usw. und auch eine Eigenschaft Autos mit einer Collection(of AutoVM).
    Sieht iwie redundant aus, und ob das in jedem Falle einen Gewinn bringt kann man (ich zumindest) in Frage stellen.

    ErfinderDesRades schrieb:

    Sieht iwie redundant aus, und ob das in jedem Falle einen Gewinn bringt kann man (ich zumindest) in Frage stellen.

    Wer sagt das MVVM in jedem Falle gut ist?
    Auf den ersten Blick ist es Redundant - ja, bei näherer Betrachtung ist von Redundanz keine Rede mehr. Wenn man es so vergleicht schon, weil in diesem Beispiel ein und die selben Props vorhanden sind, was in der Praxis sehr, sehr selten der Fall ist.
    Aber das steht ja jetzt gar nicht zur Diskussion, das ist nun mal MVVM und ob dir das jetzt gefällt oder nicht musst du für dich entscheiden. Genauso wie jeder andere.
    Doch du kannst gerne einbringen wie DU dir das vorstellen würdest (ohne die Trennung aufzugeben).

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hallo Leute

    Da ich leider etwas zu tun hatte dauerte es diesmal ein wenig länger. Aber heute ist es soweit und ich konnte schnell ein neues Video Aufnehmen.
    Ich habe diesmal versucht es schnell zu erstellen. Die Techniken sollten ja nun bereits bekannt sein.

    Viel spaß damit :!:

    Hier gehts zum letzten Tut!

    Schöne Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Nofear23m schrieb:

    Ohne eine Zeile VB Code


    Man muss aber fairerweise sagen, dass stattdessen mehrere Dutzend Zeile XAML-Code.

    Aus dem T&T verschoben. ~Thunderbolt

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

    @vb_fan Das ist richtig. Ich persönlich finde XAML Code aber übersichtlicher und schlanker.
    Hast du mal versucht ein solches Control inkl. Animation in reinem Code zu bauen? Das ist sicher nicht ganz so übersichtlich denke ich.

    Wollte damit eigendlich nur darauf Hinweisen das man hierfür eben auch keinen Code benötigt damit jeder weis, wir Arbeiten noch/wieder rein in XAML.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    @Nofear23m
    Also deine Tut sind für mich schon sehr hilfreich, und für mich als Absoluter Neuling schon sehr informativ.
    Wann kommt das nächste Video, du Hängst hinterher. :D *scherz*

    OT:
    Ich habe zu beginn immer "Semmel" verstanden.... bis ich mal gecheckt habe das du damit XAML meinst. :D
    Und Du hämmerst ganz schön auf den Tasten rum, nächste Tastatur schon bestellt? :D
    Hallo @Akanel

    Danke erstmel für dein Lob.

    Ich weis, leider hänge ich etwas hinterher. Ich habe die nächsten zwei Kapitel auch bereits vorbereitet, komme nur leider nicht dazu das Video schnell zu machen da ich im Moment auch ein wenig eingespannt bin. Das wird sich aber wieder bessern, so viel kann ich bereits sagen.

    Was dein Einwand mit "Semmel" angeht, ist witzig das du Semmel verstehst, aber viel unterschied ist ja nicht, mach spricht es nämlich wirklich so aus.

    Extensible Application Markup Language, oder XAML ("xsämmel" ausgesprochen), ist eine von Microsoft entwickelte XML-basierte Markupsprache.

    Quelle: msdn.microsoft.com/de-de/library/cc295302.aspx

    Keine Angst, meine Tastatur ist noch heile ;) . Wenn es stört werde ich mal sehen ob ich das mit meinem Micro besser hinbekomme das mana das nicht so hört.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##