diverse Fehler im Designer und beim Erstellen

  • WPF

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

    diverse Fehler im Designer und beim Erstellen

    Heyho,

    habe mir gedacht, ich bastel mir aus Spaß eine kleine Warenwirtschaft nach besten MVVM-manieren, um da endlich mal durchzublicken :)

    Grundstruktur steht, sprich RelayCommand, Navigation, Models, ViewModels und Views...

    Jetzt bekomme ich aber mir unerklärliche Fehler...?

    Zum einem kann ich auf einmal mein Haupt-ViewModel nicht mehr als DataContext festlegen...siehe Bild1. In diesem ViewModel habe ich nur eine Eigenschaft und den Konstruktur, der mir meine Navigation bastelt:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Collections.ObjectModel
    2. Namespace ViewModels
    3. Public Class MainWindowViewModel
    4. Private _TreeViewItems As ObservableCollection(Of TreeViewNavigation)
    5. Property TreeViewItems As ObservableCollection(Of TreeViewNavigation)
    6. Get
    7. Return _TreeViewItems
    8. End Get
    9. Set(value As ObservableCollection(Of TreeViewNavigation))
    10. _TreeViewItems = value
    11. End Set
    12. End Property
    13. Sub New()
    14. TreeViewItems = New ObservableCollection(Of TreeViewNavigation)
    15. 'Erste Gruppe
    16. Dim Stammdaten As New TreeViewNavigation("Stammdaten")
    17. Dim StammdatenAnlegen As New TreeViewNavigation("Stammdaten anlegen")
    18. StammdatenAnlegen.Add(New TreeViewNavigation("Kunden") With {.ViewModel = New CustomerViewModel})
    19. StammdatenAnlegen.Add(New TreeViewNavigation("Artikel"))
    20. StammdatenAnlegen.Add(New TreeViewNavigation("Warengruppen"))
    21. Stammdaten.Add(StammdatenAnlegen)
    22. Stammdaten.Add(New TreeViewNavigation("Kunden") With {.ViewModel = New CustomerListViewModel})
    23. Stammdaten.Add(New TreeViewNavigation("Artikel"))
    24. Stammdaten.Add(New TreeViewNavigation("Warengruppen"))
    25. Dim Vorgänge As New TreeViewNavigation("Vorgänge")
    26. Dim VorgangAnlegen As New TreeViewNavigation("Vorgang anlegen")
    27. VorgangAnlegen.Add(New TreeViewNavigation("Angebot"))
    28. VorgangAnlegen.Add(New TreeViewNavigation("Auftragsbestätigung"))
    29. VorgangAnlegen.Add(New TreeViewNavigation("Rechnung"))
    30. Vorgänge.Add(VorgangAnlegen)
    31. TreeViewItems.Add(Stammdaten)
    32. TreeViewItems.Add(Vorgänge)
    33. End Sub
    34. End Class
    35. End Namespace​


    Ebenfalls möchte mein MainWindow auch nicht mehr funktionieren...siehe Bild2.

    Spoiler anzeigen

    XML-Quellcode

    1. ​<Window x:Class="MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:local="clr-namespace:Warenwirtschaft.UI"
    7. xmlns:VM="clr-namespace:Warenwirtschaft.Logik.ViewModels;assembly=Warenwirtschaft.Logik"
    8. xmlns:views="clr-namespace:Warenwirtschaft.Logik.Views;assembly=Warenwirtschaft.Logik"
    9. mc:Ignorable="d"
    10. Title="Warenwirtschaft" Height="720" Width="1280">
    11. <Window.DataContext>
    12. <VM:MainWindowViewModel />
    13. </Window.DataContext>
    14. <Window.Resources>
    15. <DataTemplate DataType="{x:Type VM:CustomerViewModel}">
    16. <views:CustomerView />
    17. </DataTemplate>
    18. <DataTemplate DataType="{x:Type VM:CustomerListViewModel}">
    19. <views:CustomerListView />
    20. </DataTemplate>
    21. </Window.Resources>
    22. <Grid>
    23. <Grid.ColumnDefinitions>
    24. <ColumnDefinition Width="2*" />
    25. <ColumnDefinition Width="8*" />
    26. </Grid.ColumnDefinitions>
    27. <TreeView Grid.Column="0" Name="tvNavgiation" FontSize="14" ItemsSource="{Binding Path=TreeViewItems}">
    28. <TreeView.ItemTemplate>
    29. <HierarchicalDataTemplate ItemsSource="{Binding Path=SubTreeViewNavigation}">
    30. <TextBlock Text="{Binding DisplayName}" />
    31. </HierarchicalDataTemplate>
    32. </TreeView.ItemTemplate>
    33. </TreeView>
    34. <ScrollViewer Grid.Column="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
    35. <ContentControl Content="{Binding ElementName=tvNavgiation, Path=SelectedItem.ViewModel}" />
    36. </ScrollViewer>
    37. </Grid>
    38. </Window>


    Und zu all dem sagt er mir noch, er kann die Klassenbibliothek, welche die Logik enthällt, nicht finden...Kann diese nicht mal kompilieren..
    Auch sagt er mir sporadisch, dass es keine Methode "Query" geben würde (von Dapper).
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports Dapper
    2. Imports Warenwirtschaft.Logik.Models
    3. Imports System.Configuration
    4. Imports System.Data.Common
    5. Imports System.Data.SqlClient
    6. Public Class SqlDataAccess
    7. Private Shared Function GetConnection() As DbConnection
    8. Return New SqlConnection(ConfigurationManager.ConnectionStrings("WaWiDb").ConnectionString)
    9. End Function
    10. Shared Function GetCustomers() As List(Of CustomerModel)
    11. Const Sql = "SELECT * FROM Address"
    12. Using con = GetConnection()
    13. Return con.Query(Of CustomerModel)(Sql)
    14. End Using
    15. End Function
    16. End Class​


    Und zum Schluss eine Verständnisfrage :)
    Ich habe all meinen VM's ein Interface spendiert zur Navigation (IPageViewModel) mit nur einer, sinnlosen, Eigenschaft "Name". Anhand dessen Zeige ich die entprechende View an über ein ContentControl sowie DataTemplates. Habe mir dazu eine simple Klasse zur Hierachiebildung geschrieben:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. ​Imports System.Collections.ObjectModel
    2. Imports Warenwirtschaft.Logik.Interfaces
    3. Public Class TreeViewNavigation
    4. Private _SubTreeViewNavigation As ObservableCollection(Of TreeViewNavigation)
    5. Property SubTreeViewNavigation As ObservableCollection(Of TreeViewNavigation)
    6. Get
    7. Return _SubTreeViewNavigation
    8. End Get
    9. Set(value As ObservableCollection(Of TreeViewNavigation))
    10. _SubTreeViewNavigation = value
    11. End Set
    12. End Property
    13. Private _DisplayName As String
    14. Property DisplayName As String
    15. Get
    16. Return _DisplayName
    17. End Get
    18. Set(value As String)
    19. _DisplayName = value
    20. End Set
    21. End Property
    22. Private _ViewModel As IPageViewModel
    23. Property ViewModel As IPageViewModel
    24. Get
    25. Return _ViewModel
    26. End Get
    27. Set(value As IPageViewModel)
    28. _ViewModel = value
    29. End Set
    30. End Property
    31. Sub New(ByVal Name As String)
    32. Me.DisplayName = Name
    33. SubTreeViewNavigation = New ObservableCollection(Of TreeViewNavigation)
    34. End Sub
    35. Sub Add(ByVal item As TreeViewNavigation)
    36. SubTreeViewNavigation.Add(item)
    37. End Sub
    38. End Class

    Ändere ich nun die Eigenschaft ViewModel dieser Klasse vom Typ IPageViewModel auf Type (sodass ich dann GetType(ViewModel) aufrufen kann), funktioniert die ganze Navigation nur so "halb". Er navigiert schon auf das richtige ViewModel, zeigt mir aber quasi nur ViewModel.ToString() an statt die eigentliche View. Hoffe das ist verständlich. :D

    Ich bin um jeden Hinweis sehr dankbar :)
    Bilder
    • bild1.png

      13,05 kB, 528×115, 57 mal angesehen
    • bild2.png

      12,19 kB, 398×118, 55 mal angesehen
    Hallo

    OK, ich versuchs mal.

    Zu Bild 1.
    Irgendwo im parameterlosen Konstruktor (der vom Designer aufgerufen wird, da du den DatenContext fest angibst) hast du eine NullRefernceException.

    Das kann überall sein. Auch tiefer in der Hirarchie. Wenn z.b. New TreeViewNavigation("Stammdaten") aufgerufen wird, wird dann in diesem Konstruktor die Eigenschaft ViewModel instanziiert? Wenn nicht ist diese ja Nothing richtig? Was passiert in StammdatenAnlegen? Hier kann das auch passieren. Am besten ist du Unterscheidest im Konstruktor ob du dich in der DesignTime befindest oder nicht, und führst den Code nur zur Laufzeit aus, und einen eigenen code zur DesignTime in welchem du feste Dummydaten erstellst. Siehe meine vielen Demoprojekte wie z.b. WPFNotes.

    Zu Bild 2. Hast du vieleicht das Window in einen anderen Namespace verschoben. Mir graut er findet die Klasse "MainWindow" nicht. Also die CodeBehind.

    KingLM97 schrieb:

    Und zu all dem sagt er mir noch, er kann die Klassenbibliothek, welche die Logik enthällt, nicht finden...Kann diese nicht mal kompilieren..

    Na wenn du die nicht kompilieren kannst kann er sie auch nicht finden. Wie denn, ist ja nicht da wenn nicht kompiliert. Warum kannst du sie nicht kompilieren? Fehler?

    KingLM97 schrieb:

    zeigt mir aber quasi nur ViewModel.ToString() an statt die eigentliche View

    Dann greift das DataTemplate nicht. vergewissere dich das keine Bindingfehler in der Ausgabe vorhanden sind und die Typen korrekt angegeben wurden. Dann wird das Template auch korrekt geladen.

    Ansonsten wäre ein Beispielprojekt bzw. mehr Code ganz gut. Sonst tu ich mir schwer das nachzuvollziehen.

    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. ##

    Danke für die Antwort, ich werde morgen Abend nochmal genauer antworten.

    Dass mein Logik-Projekt nicht kompiliert kann ich mir nicht erklären, da in diesem Projekt keine Fehler sind. Nur im UI-Projekt. Das Fehlerfenster zeigt dort auch nichts an.

    Warum greift das DataTemplate nicht? Ich habe den mit x:Type den richtig Typ angegeben. Aber das ist erstmal unwichtig.

    Die Hierarchie ist das erste überhaupt, was ich in dem Projekt erstellt habe. Nachdem es funktioniert hat, habe ich dort nichts mehr geändert. Die Eigenschaft ViewModel meiner Treeviewnavigation-Klasse muss explizit gesetzt werden, standardmäßig setze ich da nichts.

    Dass ich das MainWindow in einen anderen Namespace geschoben habe kann nicht sein, würde man anhand des Namens ja erkennen. IntelliSense Vorschläge bekomme ich trotzdem, obwohl es die beiden Fehler ausspuckt.

    So viel erstmal von mobil aus, danke
    Im zweifel kannst du es auch gerne hochladen, da es doch viele Punkte sind.
    Aber gehe es nochmals morgen durch, vieleicht erledigt sich dann einiges von selbst.

    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. ##

    Im Anhang das bereinigte Projekt.

    Dass ich mein Logikprojekt nicht kompilieren konnte, obwohl es keine Fehler hatte, ist behoben. Musste die Framework-Version einmal runter setzen, Projekt entladen, wieder laden und hochsetzen, schon ging es. Keine Ahnung...:D

    Bin den Konstruktor von meinem MainWindowViewModel Schritt für Schritt durchgegangen. Ich mache dort direkt eine SQL-Abfrage, welche ohne Probleme funktioniert. Auch sonst ist es nirgends abgestürzt. Und ja, im Konstruktor wird die ViewModel-Eigenschaft nicht initialisiert.
    Die Navigation funktioniert trotzdem, auch wenn weiterhin "Window" und "Application" (aus der Application.xaml) nicht "bekannt" sind. Keine Ahnung..
    Dateien
    Also wenn ich das richtig sehe bleibt ja nur noch der Fehler das der Designer meint "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt" richtig?

    Das liegt daran das du im Konstruktor (wie du ja richtig sagst) eine DB Verbindung aufbauen willst. Das klappt zur Laufzeit wunderbar. Der Designer kann aber keine Verbindung aufbauen, wäre auch nicht gut. Es gibt ein paar Tricks das dies trotzdem geht, es ist aber davon abzuraten. Der Designer wird in die Knie gehen.

    Deshalb unterscheidet man immer ob man im Designtime ist oder nicht.
    Folgende Code im CustomerListViewModel behebt den Fehler:

    VB.NET-Quellcode

    1. Sub New()
    2. If DesignerProperties.GetIsInDesignMode(New System.Windows.DependencyObject) Then
    3. Me.Customers = New ObservableCollection(Of CustomerModel) From {New CustomerModel() With {
    4. .Firstname = "Sascha", .Surname = "Patschka", .Addresses = New ObservableCollection(Of AddressModel), .Salutation = "Herr", .Type = New AddressTypeModel}}
    5. Else
    6. Me.Customers = New ObservableCollection(Of CustomerModel)(SqlDataAccess.GetCustomers)
    7. End If
    8. End Sub


    PS: Hat es einen Grund warum du keinen OR-Mapper verwendet sondern SQL Per Hand machst? Es gibt so viele Werkzeuge die einem das abnehmen. Nur eine Frage, ich finde OldSchool ja im Grunde geil.

    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. ##

    Ah, sehr schön. Das hatte ich schon einmal gesehen, mit dem "IsInDesignMode".
    Trotzdem habe ich noch die Meldung, dass "MainWindow" nicht gefunden wurde :(

    Ich benutze Dapper für meine SQL-Abfragen, auf der Arbeit schreibe ich genug "OldSchool" :P.
    Hallo

    Verwendest du VS 2019 16.2.x ?

    Ist ein Bug: developercommunity.visualstudi…4-%E9%97%AE%E9%A2%98.html

    MS ist dran das zu fixen. Habe bei mir gerade ein Update auf 16.2.1 gemacht und der Fehler ist noch da. Laut dem Thread im Link ist es in der 16.3 Preview auch noch drinnen. Ein wenig geduld, die Releasezyklen sind eh extrem kurz im Moment.

    Aber es kompiliert ja. ;)

    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. ##