Binding scheint nicht (richtig) zu greifen

  • WPF

Es gibt 35 Antworten in diesem Thema. Der letzte Beitrag () ist von MichaHo.

    Binding scheint nicht (richtig) zu greifen

    Hallo,
    ich habe mein aktuelles Projekt mit dem Tutorial und dem Beispiel WPFNotes von @Nofear23m von WinForms in WPF nachgebaut.
    Scheinbar habe ich irgendwo ein Binding Problem, denn es werden weder meine Daten angezeigt, noch haben gebundene Buttons den richtigen Text...
    Ich hab gestern und heute stundenlang den Code im Step durchforstet, konnte aber kein falsch gesetztes Binding entdecken.
    Könnte jemand mal über das Projekt drüber gucken und mir vielleicht zeigen wo der Fehler liegt?
    Projekt ist im Anhang...
    Danke Euch

    EDIT: Doch selbst gefunden... Au Mann.... das Binding im MainWindow.xaml hat komplett gefehlt und ich Depp hab immer nur in den User Controls geschaut...
    Dateien
    "Hier könnte Ihre Werbung stehen..."

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

    Hallo @MichaHo

    Stimmt, da Fehlt überall das Binding. Hier muss für die Usercontrols der DatenContext gesetzt werden.

    XML-Quellcode

    1. <ucl:ucHeader Grid.Row="0" DataContext="{Binding HeaderWs}"/>
    2. <ucl:ucOsiComplete Grid.Row="1" DataContext="{Binding OsiWs}"/>
    3. <ucl:ucStatusBar Grid.Row="2" DataContext="{Binding StatusWs}"/>


    Aber das hat man eh gut gesehen anhand der BindingFehler in der Ausgabe.

    Kleiner Tipp: Schau dir nochmal (oder zum ersten mal) mein letztes Video an. Converter
    Am ende habe ich noch einen ExtraTipp mit drinnen. Ein kleiner Trick mittels converter womit man Binding Debuggen kann, was ja sonst nicht geht weil das die WPF für einen übernimmt.
    Setzt du also im Converter einen Haltepunkt und er geht dort nicht rein weist du das du gar nicht gebundne hast.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    @Nofear23m Geiler Tip, Danke Dir.... Habs kurz überflogen, guck mir aber gleich in der Mittagspause mal das Video dazu an....
    Binding hab ich jetzt gesetzt und soweit klaptt erst mal die Übersichten... Im Moment verzwifel ich gerade etwas am Filtern...
    Ich möchte, wenn ich die ProductionLine auswähle, das dann die dazugehörigen Instructions angezeigt werden (das klappt) und dazu dann die Main und Childsteps nur von der ausgewäjlten Instruction... das klappt leider noch nicht...
    In der ReloadData:

    C#-Quellcode

    1. internal void ReloadData()
    2. {
    3. AvailableProductionLines = new ObservableCollection<ProductionLine>(MainWs.Ctx.ProductionLines);
    4. AvailableInstructions = new ObservableCollection<Instruction>(MainWs.Ctx.Instructions);
    5. AvailableMainSteps = new ObservableCollection<MainStep>(MainWs.Ctx.MainSteps);
    6. AvailableChildSteps = new ObservableCollection<ChildStep>(MainWs.Ctx.ChildSteps);
    7. SelectedFilterProductionLine = AvailableProductionLineFilter.First();
    8. AvailableInstructionView = CollectionViewSource.GetDefaultView(AvailableInstructions);
    9. AvailableInstructionView.Filter = new Predicate<object>(InstructionFilter);
    10. SelectedFilterInstruction = AvailableInstructionFilter.First();
    11. AvailableMainStepView = CollectionViewSource.GetDefaultView(AvailableMainSteps);
    12. AvailableMainStepView.Filter = new Predicate<object>(MainStepFilter);
    13. SelectedFilterMainStep = AvailableMainStepFilter.First();
    14. AvailableChildStepView = CollectionViewSource.GetDefaultView(AvailableChildSteps);
    15. AvailableChildStepView.Filter = new Predicate<object>(ChildStepFilter);
    16. }

    die Filter:

    C#-Quellcode

    1. private bool InstructionFilter(object obj)
    2. {
    3. var instruction = (Instruction)obj;
    4. if (SelectedFilterProductionLine != null && SelectedFilterProductionLine.ID != Guid.Empty && ((Instruction)obj).LineID != SelectedFilterProductionLine.ID)
    5. return false;
    6. return true;
    7. }
    8. private bool MainStepFilter(object obj)
    9. {
    10. var mainStep = (MainStep)obj;
    11. if (SelectedFilterInstruction != null && SelectedFilterInstruction.ID != Guid.Empty && ((MainStep)obj).ID != SelectedFilterInstruction.ID)
    12. return false;
    13. return true;
    14. }
    15. private bool ChildStepFilter(object obj)
    16. {
    17. var childStep = (ChildStep)obj;
    18. if (SelectedFilterMainStep != null && SelectedFilterMainStep.ID != Guid.Empty && ((ChildStep)obj).ID != SelectedFilterMainStep.ID)
    19. return false;
    20. return true;
    21. }
    22. public ObservableCollection<Instruction> AvailableInstructionFilter => new ObservableCollection<Instruction>(AvailableInstructions.ToList());
    23. public ObservableCollection<MainStep> AvailableMainStepFilter => new ObservableCollection<MainStep>(AvailableMainSteps.ToList());
    24. private Instruction _selectedFilterInstruction;
    25. public Instruction SelectedFilterInstruction
    26. {
    27. get { return _selectedFilterInstruction; }
    28. set { _selectedFilterInstruction = value;RaisePropertyChanged();
    29. if(AvailableMainStepView != null)
    30. {
    31. AvailableMainStepView.MoveCurrentToFirst();
    32. AvailableMainStepView.Refresh();
    33. }
    34. }
    35. }
    36. private MainStep _selectedFilterMainStep;
    37. public MainStep SelectedFilterMainStep
    38. {
    39. get { return _selectedFilterMainStep; }
    40. set { _selectedFilterMainStep = value;RaisePropertyChanged();
    41. if(AvailableChildStepView != null)
    42. {
    43. AvailableChildStepView.MoveCurrentToFirst();
    44. AvailableChildStepView.Refresh();
    45. }
    46. }
    47. }

    in der Xaml:
    Instruction:

    XML-Quellcode

    1. <ListBox ItemsSource="{Binding AvailableInstructionView}" SelectedItem="{Binding SelectedFilterInstruction}" IsSynchronizedWithCurrentItem="True" HorizontalContentAlignment="Stretch" MinHeight="80">

    In der MainundChildStep:

    XML-Quellcode

    1. <ListBox ItemsSource="{Binding AvailableMainStepView}" SelectedItem="{Binding SelectedFilterMainStep}" IsSynchronizedWithCurrentItem="True" HorizontalContentAlignment="Stretch" MinHeight="80">

    XML-Quellcode

    1. <ListBox ItemsSource="{Binding AvailableChildStepView}" IsSynchronizedWithCurrentItem="True" HorizontalContentAlignment="Stretch" MinHeight="80">


    Verhalten ist folgendes:
    wenn ich in der ComboBox ProductionLine die Line auswähle, zeigt er mir die dazugehörige Instruction. wähle ich die Instruction aus, zeigt es mir aber keine Main und Childsteps.
    Wähle ich nun eine Line, wo keine Instruction dazugehören, zeigt er mir auf einmal den MainStep an. Und zwar den, der zur Instruction gehört, die aber nicht zu der Line gehört...
    Misteriös...
    "Hier könnte Ihre Werbung stehen..."
    OK, zwei Punkte

    1.) Das mit den Filtern hast du falsch verstanden. Der filter ist nicht gedacht um die beiden rechten Listboxen zu befüllen sondern eine Auflistung zu Filtern. (Suchfunktion)
    2.) Du hast da was deine Klassen angeht einen kuddelmuddel drinnen.

    Wenn du dir das Diagramm im Anhang ansiehst wirst du sehen das hier etwas nicht stimmen kann.
    Sowohl von OSIWorkspace als auch von Instruction hast du eine Verbindung zu MainStep. Warum?

    Wenn du eine Listbox hast welche auf ein Propertie des Selektierten Eintrags einer Auflistung gebunden sein soll machst du das wie folgt:

    .) Du hast eine CollectionView: Parent (diese stellt Instructions dar), auf diese ist die linke Listbox gebunden. OK

    .) Eine Listbox soll auf das Propertie MainSteps (Observablecollection Of MainStep) von der aktuell selektieren Instruction gebunden sein und diese Steps anzeigen, dann Bindest du die Listbox oder eben das UserControl wo diese Listbox drinnen ist: <uclMainChildSteps DataContext="{Binding AvailableInstructionView.CurrentItem}"/>

    In deinem Fall hast du hier ein paar Dinge durcheinandergewürfelt. Fals du nicht klar kommen solltest kann ich dir das geradebiegen, aber ich denke du willst ja selbst draufkommen.

    Tu dir keinen zwang an solltest du noch Fragen haben.

    Grüße
    Sascha
    Bilder
    • Workspace.png

      70,77 kB, 1.459×733, 20 mal angesehen
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

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

    OK, dachte mir schon das ich da irgendwas verbastelt habe.... :(
    Also nur so als Tip.... ich benötige im OsiWorkspace nur die Parent (ProductionLine) und dazu die Instruction, richtig?
    weil die Instruction erstellt ja im Konstrucktor eine MainChild und die MainChild erstellt eine Child...
    Btw. wie hast Du die Linien in dem Diagramm hin bekommen? bei mir sind da keine...
    "Hier könnte Ihre Werbung stehen..."
    Hallo

    Nur im groben. Ich gehe mal davon aus das jeder MainStep X Childsteps haben kann. Zumindest ist es so im Model definiert.

    Du hast in OSIWorkspace AviableInstructions (Observable) und AviableInstructionView
    Über die View filterst du usw.
    Die View bietet auch das Propertie CurrentItem (Das selektierte in der Listbox)

    EIN Instruction beinhaltet dann eine ObservableCollection(Of MainSteps) und eine View (Wie im OSIWorkspace)
    EIN MainStep beinhaltet dann eine ObservableCollection(Of ChildStep) - evtl. eine view wenn hier auch eine Filtermöglichkeit und/oder der CurrentItem benötigt wird.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    OK, Verwirrung perfekt.
    Also. Das Datenmodell ist so.
    1 ProductionLine kann x Instruction haben, aber 1 Instruction immer nur 1 Production Line
    1 Instruction kann x MainStep haben und umgekehrt wieder nur 1:1
    1 MainStep kann x ChildStep haben und umgekehrt 1:1

    Also sind meine Models erstmal Korrekt, richtig?
    So, nun erstell ich im OsiWorkspace eine neue Instruction, die erstellt sich eine MainStep und die erstellt sich eine Child, richtig?
    Als Views benötige ich ja dann 1 mal ProductionLine (wobei ich da nur einen Filter für brauche und erst dann eine View wenn ich das AddProductionLineWindow gebaut habe), dann benötige ich 1 Instruction View die durch ProductionLine Filter gefiltert werden kann. Plus 1 View für Main und Child Steps, wobei die Views dann immer Instruction.Current wäre...
    Diese beiden Views baue ich einmal im Instruction Model und MainStep Model oder im OsiWorkspace?
    Und wie sag ich der Methode Seed beim Erstellen der Beispieldaten, das sie einen MainStep und ChilödStep erstellen soll, der sich auf die vorher erstellte Instruction bezieht??

    Fragen über Fragen... aber so ganz Blick ichs leider noch nicht...
    "Hier könnte Ihre Werbung stehen..."

    MichaHo schrieb:

    1 ProductionLine kann x Instruction haben, aber 1 Instruction immer nur 1 Production Line

    Die ProductionLine habe oich jetzt sowieso ausser acht gelassen weil ich hier weder im View nocht in der Klasse selbst etwas von wegen Verweis sehe.
    Wo ist im Model definiert das ProductionLine X Instructions haben kann?? Die Klasse hat nur(!!) ein String Propertie
    Und auch im View zeigst du in der linken Listbox doch nur die Instructions an. Wo ist ProduktionLine??

    Vorschlag: Mach das Model korrekt, so wie du es jetzt aufgezählt hast. Dann mach ich dir einen Vorschlag für die Workspaces.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    @Nofear23m Danke für Deine Geduld, ich glaub der Schlauch ist zu Dick.....

    Also, es ist so. Die ProductionLine soll die Übergeordnete Tabelle sein (ach ich dämel, jetzt wo ichs aufschreibe fällts mir ein).....

    In ProductionLine fehlte die Zuordnung zur Instruction....
    So sollte das Datenmodell jetzt richtig sein.
    Die Production Line ist die Haupttabelle...
    "Hier könnte Ihre Werbung stehen..."
    OK, dann sollte aber die linke Listbox im View die Productionline anzeigen oder?
    Da Fehlt ja sowieso im View ne Listbox oder?

    Aber vom Prnzip her ändert sich nix von der Beschreibung oben. Nur eben eine Ebene weiter nach oben quasi.

    Ansonsten probiers mal mit der Beschreibung und wenn du fragen hast lade das Projekt hoch und dann schau ich mal drüber. Bau es mal so um wie beschrieben und mit dem aktuellen Model.

    EDIT: Wegen dem Klassendiagram. Rechtsklick auf das Property - Als Auflistung anzeigen oder so ähnlich!!

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    Hi,
    Ähm, ja, ich wollte die ProductionLine quasi auswählbar machen, weil da gibbet nur 4 Stück von.
    Das Meiste spielt sich im MainStep und ChildStep ab.
    Im Grunde sollen die MA in der Qualy eine Instruction anlegen, dabei auswählen zu welcher ProductionLine die gehört und im Nachgang sollen dann zu dieser Instruction die MainStep und ChildSteps angelegt werden.
    Hmmm.... wenn ich so darüber nachdenke, und das mit dem WPFNotes Programm vergleiche, könnte ProductionLine ja auch die Categorie sein und Notes ist meine Instruction, wobei die dann halt noch 2 Untergeordnete hat (MainStep und ChildStep) und Attachments könnte ich zur Not auch haben, denn in jedem MainStep und in jedem ChildStep muss ein Bild rein....
    Auweia....
    "Hier könnte Ihre Werbung stehen..."
    OK, jetzt verstehe ich das!!!

    Hab gerade gesehen das die ProductionLine in dem DropDown ist!!

    OK, na dann benötigst du ja eigendlich nur in Instruction ein Property CurrentProductionLine. Siehe Anhang!! Mehr nicht.

    Meintest du es so, sorry, da habe ich nicht genau nachgesehen was Productionline genau ist.

    Grüße
    Sascha
    Bilder
    • Model.png

      57,41 kB, 1.339×757, 15 mal angesehen
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    Ja genau... wobei die CurrentProductionLine Property ja meine LineID ist... in der steht die ID der ProductionLine ja drin.
    Soweit funktioniert das ja auch, ich kann eine Production Line wählen und bekomme die Instruction dazu... alles Tutti... nur mit den MainSteps und ChildSteps klappt es nicht.
    Ich weis auch nicht wound wie ich das View dafür erstellen soll....
    "Hier könnte Ihre Werbung stehen..."
    Nene, dann passt der View ja eh. Ich hab das mit Productionline nur verpeilt.
    Im Grunde passt ja nun genau das was ich in Post um 13:15 geschrieben habe. Mach genau so die Workspaces und Binde das. Dann sollte das so funktionieren.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    Hallo @Nofear23m
    so ganz will es mir noch nicht gelingen :(
    Wenn ich im OsiWorkspace die beiden Views für MainStep und ChildStep anlege, meckert das System das der Objektverweis fehlt.
    Lege ich die beiden Views in den Models an, gibt es beim Serialisieren ein Problem weil er das View nicht serialisieren kann...

    Das Video hab ich mir angeschaut und auch das mit dem Binding Tip am Ende... muss ich dann bei allen Bindings die Bindings durch den Converter jagen oder macht man das nur zum Debugen eines bestimmten Bindings?
    Bilder
    • OSI-Model.PNG

      48,09 kB, 1.082×807, 13 mal angesehen
    • OSI-Workspace.PNG

      78,26 kB, 1.137×807, 16 mal angesehen
    "Hier könnte Ihre Werbung stehen..."
    Hallo

    MichaHo schrieb:

    Lege ich die beiden Views in den Models an, gibt es beim Serialisieren ein Problem weil er das View nicht serialisieren kann...

    Logisch, dort gehört es ja auch nicht hin. PS: Es sind keine Views. Es sind wenn du so willst ViewModel-Klassen.

    MichaHo schrieb:

    muss ich dann bei allen Bindings die Bindings durch den Converter jagen oder macht man das nur zum Debugen eines bestimmten Bindings?

    Ja, zum Debuggen wenn du dir nicht sicher bist ob ein Binding korrekt ist kannst du bei dem Binding um welches es geht diesen DebugConverter draufsetzen um sehen zu können ob das binding korrekt graift und welches Objekt genau übergeben wird.

    Ich sehe auf dem Diagram jetzt leider keine Datentypen. (muss man einblenden). Wobei mir die Linie zwischen MainStep und ChildSteps suggeriert das dies keine 1:N beziehung ist oder? Soll aber oder. Es gibt ja mehrere ChildSteps richtig?

    Lade das Projekt mal hoch, ich schau es mir mal an.

    Edit: Cool, mein 1000er Post!!!

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

    Hab jetzt die beiden Diagramme noch einmal abgeändert mit Datentypen...

    Das mit den ViewModel-Klassen hab ich nicht verstanden :(
    Das Projekt liegt anbei...
    Danke Dir
    Dateien
    "Hier könnte Ihre Werbung stehen..."
    Hallo

    Ich habs jetzt mal soweit gerade gebogen. Ich habe so gut wie möglich meine Änderungen immer mit einem SPS vorangestellt.
    So kannst du die Suchfunktion (STRG + F) verwenden und alle Kommentare finde welche ich gemacht habe.

    Sorry falls ich manche dinge nicht so schön gemacht habe, C# ist nicht so meines.
    Ich habe mal die bindings für das Hauptview geradegerückt so das die MainSteps und ChildSteps korrekt angezeigt werden, der Code hat dort eh soweit gepasst.

    Wo es nicht ganz passte ist bei der neuanlage von instructions. Dort habe ich es aber soweit Kommentiert.

    EDIT: Sorry, ich musste ein paar Dinge bez. C# 7 abändern da ich hier in der Arbeit nur VS 2015 Community habe und hier kein C# 7, da fehlen mir ein paar Funktionen.
    Edit 2: Achja @MichaHo, lösche mal die XML, ich habe im seeding auch was geändert damit bessere Beispieldaten inkl. MainSteps und jeweils ChildSteps zur verfügung stehen.
    Grüße
    Sascha
    Dateien
    • WpfOsi.zip

      (181,02 kB, 9 mal heruntergeladen, zuletzt: )
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

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

    Hallo @Nofear23m Danke Dir... Das sieht gut aus soweit.
    Ich bastel mir jetzt noch nach Deinem Schema die AddMainStep und AddChildStep, dann brauch ich noch Edit und Delete und ich muss noch scheun wie ich das ganze als PDF speichere und innerhalb der Main und ChildSteps noch Steps hoch oder runter verschieben kann, mit gleichzeitiger Anpassung der StepNumber....
    Uff...
    Also passiert doch so einiges im CodeBehind... Da kann ich mir dann viel aus meinem WinForms Projekt raus holen...
    Ich zieh jetzt auch erstmal den Code noch glatt, gibt ja viele Commands im Workspace die ja jetzt im CodeBehind sind.
    So langsam kommt aber Licht ins Dunkle :)
    Der Code aus dem Code Behind kommt bei MVVM vermutlich in die ViewModel Klassen, richtig?
    Achja, eine Sache noch:

    XML-Quellcode

    1. <ucl:ucMainChildSteps DataContext="{Binding}"/>
    dies hier im OsiComplete Window. Was bedeutet es wenn hinter dem Binding nichts angegeben ist?

    Danke Dir jedenfalls sehr!

    EDIT: @Nofear23m Japp. hab ich gesehen. Hab allerdings die StepNumber angepasst, denn jede Instruction hat ja ihre eignene MainSteps und diese wiederum haben ihre eigenen ChildSteps, somit fangen die Main und ChildSteps immer bei 1 an...
    quasi so:

    C#-Quellcode

    1. internal void Seed()
    2. {
    3. LockForChanges();
    4. if(!ProductionLines.Any())
    5. {
    6. ProductionLines.Add(new ProductionLine() { Designation = "Übergreifend" });
    7. ProductionLines.Add(new ProductionLine() {Designation = "BioCel" });
    8. ProductionLines.Add(new ProductionLine() { Designation = "Flachmembran" });
    9. ProductionLines.Add(new ProductionLine() { Designation = "Kapillar" });
    10. ProductionLines.Add(new ProductionLine() { Designation = "Rohrmodule" });
    11. }
    12. if (!Instructions.Any())
    13. {
    14. Instructions.Add(new Instruction()
    15. {
    16. FormularNumber = 1000,
    17. FormularName = "TestFormular",
    18. RevisionNumber = 1,
    19. RevisionDate = DateTime.Now,
    20. LineID = ProductionLines.First(p => p.Designation == "BioCel").ID,
    21. MainSteps = new ObservableCollection<MainStep>() {
    22. new MainStep() { StepText = "Test 1 für Instruction 1", StepNo = 1,
    23. ChildSteps = new ObservableCollection<ChildStep>()
    24. {
    25. new ChildStep { StepText = "Child 1 für MainStep 1", StepNo = 1 },
    26. new ChildStep { StepText = "Child 2 für MainStep 1" , StepNo = 2 },
    27. new ChildStep { StepText = "Child 3 für MainStep 1", StepNo = 3 }
    28. } } , new MainStep() { StepText = "Test 2 für Instruction 1", StepNo = 2,
    29. ChildSteps = new ObservableCollection<ChildStep>()
    30. {
    31. new ChildStep { StepText = "Child 1 für MainStep 2" , StepNo = 1},
    32. new ChildStep { StepText = "Child 2 für MainStep 2", StepNo = 2 }
    33. } }}
    34. });
    35. foreach (MainStep mStep in Instructions[0].MainSteps)
    36. {
    37. mStep.InstructionID = Instructions[0].ID;
    38. foreach (ChildStep cStep in mStep.ChildSteps)
    39. {
    40. cStep.MainStepID = mStep.ID;
    41. }
    42. }
    43. }
    44. UnlockForChanges();
    45. SaveChanges();
    46. }

    "Hier könnte Ihre Werbung stehen..."