WPF Einarbeitung, Anwendung starten, Anwendung vorbereiten (.NET 7)

  • WPF
  • .NET 7–8

Es gibt 64 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    WPF Einarbeitung, Anwendung starten, Anwendung vorbereiten (.NET 7)

    Hallo,

    ich versuche mich in WPF einzuarbeiten, allerdings steh ich ganz am Anfang schon vor der Unwissenheit.
    Wo schreib ich denn den Code rein der beim laden der App abläuft?
    Bei Windows-Forms wäre das die Sub New des Startforms, wenn es denn ein Startform gibt, ansonsten die Sub Main im Startmodul.

    Eine Sub Main sehe ich bei WPF nicht.

    Viele Grüße

    Haudruferzappeltnoch schrieb:

    Wo schreib ich denn den Code rein der beim laden der App abläuft?


    Hängt davon ab, wie du die App aufbaust, standart gibst du eine "StartUpUri" an, dieses Fenster wird dann beim Start verwendet. Schau mal in der Application.xaml:

    XML-Quellcode

    1. StartupUri="MainWindow.xaml"


    Wenn du nun auch in der Application.xaml.vb schaust, ganz leer. Aber du kanst dort z.B. das StartUp und Exit(natürlich auch mehr) überschreiben. Das wäre dann wie dein "Main" Einstiegspunkt. Gibst du keine StartUpUri an, könntest du auch hier selbst ein Window erstellen und zeigen.

    VB.NET-Quellcode

    1. Class Application
    2. ' Application-level events, such as Startup, Exit, and DispatcherUnhandledException
    3. ' can be handled in this file.
    4. Protected Overrides Sub OnStartup(e As StartupEventArgs)
    5. MyBase.OnStartup(e)
    6. End Sub
    7. Protected Overrides Sub OnExit(e As ExitEventArgs)
    8. MyBase.OnExit(e)
    9. End Sub
    10. End Class

    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    du kannst dir auch einen meiner Uploads im Wpf-Tut-Bereich zu Gemüte führen. Und zurnot mit F10 starten und von anfang an im Einzelschritt durchsteppen.
    Wenn cih recht erinnere findet mein ganzer Startup im MainViewmodel statt.
    Nur eine Einstellung bezüglich CurrentCultur fäht bei mir im App.xaml-Codebehind herum - weil muss noch früher da sein.
    Aha, überschreiben heißt das gibt es schon irgendwo. In Windows Forms gibt es zum Beispiel den Designer-Code in denen einigen Sachen gemacht werden, aber ausgelagert werden können. Ich denke mal die Sub New wäre da das häufigste.
    Solche Designer-Codes habe ich bei WPF jetzt nicht gesehen.

    Bei mir ist MainWindow.xaml auch die StartUpUri.
    Ich habe auch eine MainWindow Class. (Hier eine kleine Extrafrage nebenbei, warum gibt es hier kein Public, Friend, etc. Attribut?)
    Ist das dann wie mein Form1?
    Da habe ich jetzt auch mal wie bei Windows Forms eine Sub New reingepackt. Übrigens generiert die auch eine InitializeComponents() welche scheinbar in einer MainWindow.g.i.vb definiert ist. Das ist dann wohl der Designer, nur etwas stärker versteckt.

    @ErfinderDesRades Ist das MainViewModel denn das Analogon zum StartForm bei Windows Forms?

    Haudruferzappeltnoch schrieb:

    Das ist dann wohl der Designer, nur etwas stärker versteckt.


    Naja sowas wie in Forms haben wir nicht. Wir haben die Application-Klasse, dazu Application.xaml, wo du weitere ResourceDictionaries/Styles etc. reinmachen kannst. Dann haben wir Window.xaml und Window.xaml.vb.

    Haudruferzappeltnoch schrieb:

    Ist das MainViewModel denn das Analogon zum StartForm bei Windows Forms?


    Das kommt dann zum Einsatz wenn man das MVVM-Pattern anwendet. Die ViewModel-Klassen(die implemetieren INotifyPropertyChanged) verwendet man dann als DataContext für die Windows, an Properties in den ViewModelklassen wird dann gebunden, die Bindung geben wir dann im XAML an. Bei MVVM nutzt man so gut wie keinen bishin zu keinen CodeBehind, das finde ich aber Geschamackssache, da sind die Meinungen doch recht geteilt. Ich vermeide wo es geht, bin aber nicht abgeneigt, welchen einzusetzen. CodeBehind wäre die MainWindow-Klasse.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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

    oder gugge meine Wpf-Grundlagen - Tuts (also die, die mit "Grundlagen" markiert sind).
    Ist viel weniger durchzuarbeiten, weil die versuchen nicht, die ganze Wpf abzudecken.
    Sondern beschäftigen sich direkt mit den Kernthemen: MVVM-Pattern, Databinding + DataContext, Delegate-/RelayCommand-Commands und Templating-Wesen
    Ich empfehle denn auch diese Reihenfolge:
    Anwendungsstruktur, BindingPicking, ControlTemplates

    Das erstmal durchkauen - vorher kannste kaum sinnvolle Fragen stellen, weil was du von WinForms kennst, musste zu 80% neu denken.
    ZB Codebehind wie die MainWindow-Class widerspricht dem MVVM-Pattern - derlei wird nur ausnahmsweise genutzt, wenns garnet anders geht.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Haudruferzappeltnoch schrieb:

    @ErfinderDesRades Ist das MainViewModel denn das Analogon zum StartForm bei Windows Forms?
    Nein - es ähnelt eher den typisierten Datasets, wie ich sie in WinForms verwende.
    Ich siedele ja komplexe Business-Logik vorzugsweise in partiale Klassen des typDatasets an - Stichwort Trennung von BL und GUI.

    MVVM treibt das nu auf die Spitze: Es gibt gar keinen prozeduralen Code mehr im GUI: kein Button_Click - Event, kein Combobox_SelectedIndexChanged etc.
    Das gesamte Datenmodell inklusive aller Logik ist in den Klassen des Viewmodels codiert, und daran das GUI gebunden.

    Das MainViewmodel ist nu eine zentrale Viewmodel-Klasse, die von jedem Sub-Viewmodel eine oder mehrere Instanzen hält.
    Verschiedene GUI-Teile binden an (und präsentieren damit) verschiedene Sub-Viewmodel - das MainViewmodel ist wie der Stamm eines Baumes - alle Äste gehen davon aus.

    Insofern ists durchaus ein Start-Objekt der Anwendung - aber ist eben genau kein Start-Form. Eher ein Start-Datenmodell.

    Hmm - also das richtige StartObjekt ist die App.Xaml, und da steht folgendes drinne:

    XML-Quellcode

    1. <Application x:Class="Application"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:my="clr-namespace:SizeBrowser"
    5. StartupUri="MainWindow.xaml">
    6. <Application.Resources>
    7. <my:MainModel x:Key="Mainmodel"/>
    8. </Application.Resources>
    9. </Application>
    Nämlich da wird ein Mainmodel instanziert, und den Resourcen der Anwendung zugefügt.
    Alle GUI der Anwendung kann nun an dieses Mainmodel binden:

    XML-Quellcode

    1. <Window x:Class="MainWindow"
    2. [...]
    3. DataContext="{Binding Source={StaticResource Mainmodel}}">


    Ok, in App.Xaml wird auch der StarupUri angegeben - das Window, was zum Startup öffnen soll. Aber das könnte auch ein anderes Window sein.



    Inzwischen lege ich das Mainmodel auch garnet mehr in die App.Xaml-Resourcen, sondern binde alle GUI an eine statische Singleton-Instance des MainModel:

    XML-Quellcode

    1. <Window x:Class="wndPong3"
    2. [...]
    3. DataContext="{Binding Source={x:Static vm:Mainmodel.Instance}}">

    Dazu der Singleton im MainModel:

    VB.NET-Quellcode

    1. Public Class Mainmodel : Inherits NotifyPropertyChanged
    2. Public Shared ReadOnly Instance As New Mainmodel
    3. '...


    Lad dir das "Kein Pong"-Tut - das ist auch schick anzugugge.

    Dieser Beitrag wurde bereits 8 mal editiert, zuletzt von „ErfinderDesRades“ ()

    ErfinderDesRades schrieb:

    Dazu der Singleton im MainModel:


    Füge doch bitte noch einen privaten Konstruktor hinzu, hier gibt es garatiert Leute denen SingleTon nicht geläufig ist und das so übernehmen, weil sie es nicht besser wissen. Klar steht da '... in der Codebox, aber wie gesagt, nicht jeder weis das der ctor dann privat zu sein hat.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    @ErfinderDesRades Ich habe das Tutorial angeschaut, leider konnte es mir noch keine Frage beantworten.
    Gerade im ersten Tutorial Anwendungsstruktur, wird mir ganz deutlich, dass du einige Sachen an WPF verstanden hast, die für mich nicht ablesbar sind.

    Ich war im MainWindow.xaml.vb und habe eine Sub New gemacht. Diese läuft beim Start ab. Ich verstehe, dass das Codebehind ist.

    Bei dir läuft als erstes die Sub New von MainModel, da ist die Frage warum? Das ist ja im Endeffekt eine selbstgebaute Klasse, das kann ja nicht der grundlegende Einstiegspunkt sein.
    Wer sagt denn Dim x = New MainModel?
    Auch halte ich es für möglich, dass die Helpers etwas verschleiernd sind, wenn es darum geht zu verstehen was gemacht wird.
    Wenn MainModel keine MainmodelBase hätte, von der es erbt, würde dadurch irgendwas verloren gehen?

    DTF schrieb:

    Füge doch bitte noch einen privaten Konstruktor hinzu,
    brauche ich nicht.
    Das Feld ist Shared Readonly - das kann nicht durch was anneres ersetzt werden.
    Ja, ok - iwelche Trollos mögen eine Instanz vom MainViewmodel sich erstellen, und konfuses Zeug damit anrichten - also bitte:

    VB.NET-Quellcode

    1. Public Class Mainmodel : Inherits NotifyPropertyChanged
    2. private Sub New()
    3. End Sub
    4. Public Shared ReadOnly Instance As New Mainmodel
    5. '...




    Haudruferzappeltnoch schrieb:

    Bei dir läuft als erstes die Sub New von MainModel, da ist die Frage warum? Das ist ja im Endeffekt eine selbstgebaute Klasse, das kann ja nicht der grundlegende Einstiegspunkt sein.
    Wer sagt denn Dim x = New MainModel?
    habich doch gesagt: im Xaml steht:

    XML-Quellcode

    1. <my:MainModel x:Key="Mainmodel"/>
    Da wird son Ding erstellt, und den Resourcen zugefügt.
    App.Xaml ist der Einstiegspunkt der Anwendung.
    Und Xaml kann zwar keinen prozeduralen Code aufrufen, aber Konstruktoren musses ja aufrufen können, sonst würde was man im Xaml hinschreibt und ineinanderschachtelt ja nie ein Window ergeben mit eingeschachtelten View-Elementen.
    Wenn du es so genau wissen willst, kannste dir auch das Grundlagen-Tut zur Xaml-Syntax reintun.
    Ich hab gedacht, das braucht man eher nicht, weil man Xaml intuitiv weitgehend versteht (aber eben nicht genau).

    Haudruferzappeltnoch schrieb:


    Wenn MainModel keine MainmodelBase hätte, von der es erbt, würde dadurch irgendwas verloren gehen?
    ja natürlich, sonst würde ichs nicht erben lassen.
    aber ladt dir "kein Pong", und betrachte da die Version3. Die bindet an einen Singleton, was einiges vereinfacht.
    U.U. (habich vergessen) ist dann die Basisklasse sogar verzichtbar.

    Vielleicht auch nicht,
    weil bei mir soll jedes MainViewModel auch zur Designzeit Daten bereitstellen, damit man im Wpf-Designer vernünftig arbeiten kann.
    Daher muss jedes MainViewmodel unterscheiden können, ob es im Designer läuft oder nicht. (IsProvisional)
    Jo, und Dinge, die jedes können soll - sowas verlegt man gerne in Basisklassen, dann können sie es erben. :D
    Kein gross Hexenwerk.

    Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von „ErfinderDesRades“ ()

    naja, wenn du in deim Leben nur 1 Wpf-Anwendung machen willst, brauchst du MainViewmodel-Funktionalität nicht auslagern.
    Und wenn deine Anwendung nur eine ViewmodelKlasse hat, und nie jemals weitere dazukommen werden - dann brauchst du auch keine ViewmodelBase.

    Aber da ist doch auch garnet so viel kompliziertes drin, oder?
    Nur INotifyPropertyChanged und IsInDesignmode - oder habich was vergessen?
    Habe ein bisschen rumprobiert.
    Je nachdem was ich im Sub New mache, laden im Designer schon Elemente einer Listbox oder nicht.
    Funktioniert im Designer

    VB.NET-Quellcode

    1. Class MainWindow
    2. Public Sub New()
    3. InitializeComponent()
    4. _Pakete = New ObservableCollection(Of Paket)
    5. _Pakete.Add(New Paket(1, "A 18", 1, True))
    6. DataContext = Me
    7. End Sub
    8. Public Property Pakete As ObservableCollection(Of Paket)
    9. End Class

    Funktioniert nicht im Designer:

    VB.NET-Quellcode

    1. Class MainWindow
    2. Public Sub New()
    3. InitializeComponent()
    4. Dim DS1 As New MyData.DataSet1
    5. DS1.ReadXml("DS1.xml")
    6. _Pakete = New ObservableCollection(Of Paket)
    7. For Each p In DS1.Paket
    8. _Pakete.Add(New Paket(p.ID, p.Abstellplatz, p.InhaltMenge, p.Einheitlich))
    9. Next
    10. DataContext = Me
    11. End Sub
    12. Public Property Pakete As ObservableCollection(Of Paket)
    13. End Class

    Gibt es eine Regel dafür welche Operationen im Designer ausgeführt werden und welche nicht?
    ich würd nie zur Designzeit etwas aus einer Datei laden - allenfalls auf korrekte Weise aus den Wpf-Resourcen.
    Gut möglich auch, dass der Dateipfad zur Designzeit in ein anderes Directory verweist - probierma mittm vollqualifizierten Dateinamen.

    Btw - wieso biste denn da im MainWindow unterwegs? Dassis ja komplett gegen MVVM. Da brauch man im Grunde ja kein Databinding, wenn das Window die Daten selber ist.

    Haudruferzappeltnoch schrieb:

    MVVM hab ich noch nicht
    Also vergisses.
    WPF muss man mit MVVM anfangen, Templates sind nachrangig. Templates ohne MVVM sind - nur Klickibunti.

    Haudruferzappeltnoch schrieb:

    Wofür ist das DataContext = Me?
    dassiis Databinding, wie man es genau nicht machen sollte.
    Jedes Visual - also auch ein Window - hat einen DataContext - entfernt vergleichbar der DataSource von WinForms-DGV, -Combobox, -Listbox.
    Diesen DataContext auf sichselbst einzustellen ist einfach MIst.
    Und noch dazu im CodeBehind! DataContexte lege man bitte im Xaml fest!

    Also iwelches KlickiBunti kann man so zum Laufen bringen, aber Datenverarbeitung erlernst du so nie.



    Also strukturier deine Anwendung richtig, mit View und Viewmodel.
    Im Viewmodel hast du Daten und vb.net-Code. Im View bindest du daran, mit Xaml.

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

    ErfinderDesRades schrieb:

    Und noch dazu im CodeBehind! DataContexte lege man bitte im Xaml fest!


    Bitte verbreite keinen solchen Unsinn. Spätestens wenn du einen DI-Container verwendest und Dependency Injection einsetzt, wirst du es nicht in XAML definieren können, da XAML nur den Basiskonstruktor verwenden kann.

    @Haudruferzappeltnoch
    Der DataContext ist das Objekt, aus dem das aktuelle Objekt seine Daten bezieht. In diesem Fall bezieht sich das MainWindow auf seine Daten über seine Eigenschaften (Paket).
    Eine wichtige Regel betrifft das Designtime-Verhalten. Die Designdaten werden immer über den parameterlosen Konstruktor abgerufen. Wenn du uns deinen XAML-Code zeigst, können wir eventuell weiterhelfen. Bevor du mit MVVM anfängst, ist es wichtig, das Binding-Konzept zu verstehen. Andernfalls wird dir MVVM nicht viel nützen.

    In neuen Technologien wie MAUI gibt es oft keinen Designtime-Support.
    Das Konzept des Design-Time ist manchmal aufwendig und in einigen Fällen
    sogar unmöglich. Es gibt Situationen, in denen Daten nur zur Laufzeit
    verfügbar sind, wie beispielsweise Daten aus APIs, Datenbanken oder
    allgemeine Services. Verschiedene Ansätze wie d:DataContext oder if (DesignerProperties.GetIsInDesignMode(this))
    wurden unternommen, um Daten während der Designtime anzuzeigen. Doch
    wenn dein Projekt sehr groß und komplex wird, führt kein Weg daran
    vorbei, dein eigenes Designtime-Verhalten zu programmieren. Hierbei kann
    beispielsweise die Verwendung eines DesigntimeViewModels oder anderer
    Techniken hilfreich sein. In deinem Fall sollte es jedoch gut
    funktionieren.


    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Amro“ ()