Mehrere Listboxen an gleiche Daten binden.

  • WPF

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

    Mehrere Listboxen an gleiche Daten binden.

    Hallo,
    ich versuche gerade die Daten einer einzigen Quelle auf mehrere Listboxen aufzuteilen.
    Jede LB zeigt jeweils nur die nach einem Kriterium gefilterten Daten an. Eine der Eigenschaften meiner Datenklasse heist "Workcenter".
    Jede der LB zeigt jeweils nur die Daten eines "Workcenters" an. Man könnte sagen, die Daten werden in den LB sortiert angezeigt.
    Um das zu erreichen musste ich schon mal eine separat Ansicht/View (ICollectionView) zum Binden an die jeweiligen LB bereitstellen.

    Auf dem Fenster ist neben den verschiedenen LB auch noch eine "grosse" Textbox vorhanden, welches sowohl zum Anzeigen als auch dem Bearbeiten einer gemeinsamen Eigenschaft der Daten dienen soll.

    Und jetzt versuche ich zu erreichen, dass egal in welche der LB ein Eintrag ausgewählt wird, die mit der Textbox gebundene Eigenschaft in der TB angezeigt werden soll.

    Ich hab schon mal in meinem ViewModel eine "SelectedItem" Eigenschaft angelegt (an welche meine TextBox gebunden werden soll), weil ich glaube, dass es nicht ohne gehen wird.

    Könnte bitte jemand mir das Prinzip sowie die Vorgehensweise erklären wie ich erreichen könnte, dass mein ViewModel mit bekommt, dass in einer (der vielen) ListBoxen die "selection" geändert hat.
    Und wie wird dann das "selectedItem" der angeklickten LB an das ViewModel übergeben. ?(


    Im Voraus schon mal vielen Dank,
    Jeiss
    Hallo

    Jeiss schrieb:

    Jede LB zeigt jeweils nur die nach einem Kriterium gefilterten Daten an

    Du hast also mehrere Properties in deinem ViewModel, korrekt?

    Jeiss schrieb:

    Um das zu erreichen musste ich schon mal eine separat Ansicht/View (ICollectionView) zum Binden an die jeweiligen LB bereitstellen.

    Für jede Listbox hast du also ein eigene Property vom Typ ICollectionView richtig?

    Jeiss schrieb:

    Ich hab schon mal in meinem ViewModel eine "SelectedItem" Eigenschaft angelegt

    Wenn du die ICollectionView verwendest benötigst du das gar nicht. Die hat das Property "CurrentItem".

    Jeiss schrieb:

    dass mein ViewModel mit bekommt, dass in einer (der vielen) ListBoxen die "selection" geändert hat.

    Über das besagte CurrentItem Property.

    Wenn ich das aber richtig verstehe haben alle ListboxItems den selben Datentyp richtig? Wenn dies der Fall ist benötigst du ja nur ein Property im ViewModel welches des zuletzt selektierte Item hält.
    Die IcollectionView bietet hierfür das Event "CurrentChanged" an. Du setzt also für jede ICollectionView in deinem ViewModel einen Handler auf die selbe Sub, und schreibst das Item in dieses Property. Fertig.

    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,
    ​danke, dass ihr so schnell auf meine Frage geantwortet habt.
    ​ErfinderDesRades:
    ​Den Artikel den du mir zu studieren empfiehlst, ist genau der Artikel den ich mir angekuckt hab bevor ich meine Frage gepostet hab.
    ​Hab aber gedacht, der wäre nicht die Antwort auf mein Problem, da ich ja mehrere von diesen Listboxen hab.... Ich muss auch zugeben, dass ich schon mehrere Tage an einer Lösung zu meinem Problem suche......
    ​Und da geht irgendwann gar nichts mehr.... Aber ich schau mir den Artikel nochmal an, jetzt da ich weiß, dass ich die Lösung zu meinem Problem doch darin finden kann.

    ​NoFear23m:
    ​Ja du liegst mit deinen Vermutungen genau richtig.
    ​Ich hab für jede Listbox eine ICollectionView Eigenschaft im VM. Und alle LB enthalten Daten vom gleichen Datentyp (UrgentOrders)
    ​Ok, CurrentItem ist schon mal ein guter Tip, werde ich studieren.
    ​In meinem ViewModel hab ich ja schon mal eine "SelectedUrgentOrder" Property, jetzt muss ich nur noch rausfinden wie ich da den zuletzt angeklickten Item da rein kriege....
    ​Die IcollectionView bietet hierfür das Event "CurrentChanged" an. Du setzt also für jede ICollectionView in deinem ViewModel einen Handler auf die selbe Sub, und schreibst das Item in dieses Property. Fertig.

    ​Ok, das versuch ich hin zu kriegen.... Ich hab das ja richtig verstanden, ein Event vom ICollectionView....ok?! Wenigstens sind wir dann schon mal im ViewModel.... Gut das scheint der Weg zu sein.

    ​Da ich ja jetzt wenigstens die Richtung weiß, ist es für mich auch einfacher. Ich weiß jetzt wenigstens wonach ich suche...

    Ich bedanke mich mal für die hilfreichen Tipps, und melde mich dann bestimmt bald mit spezifischeren Fragen wieder.
    Jeiss

    Jeiss schrieb:

    Ich hab das ja richtig verstanden, ein Event vom ICollectionView....ok?!

    Vollkommen richtig.

    Du hast ja mehrere ICollectionView`s. Jetzt machst du dir ein im VM ein Property z.b. in deinem Fall LastSelectedUrgentOrder welches von selben Typ ist wie die Items in deinen ICollectionView`s.
    Für jedes ICollectionView in deinem VM Abonnierst du das Event CurrentChanged auf ein und die selbe Sub. Nennen wir diese jetzt mal UrgendSelected.
    In dieser Prozedur machst du nichts anderes als das du von sender (ist ja eine ICollectionView) den CurrentItem in dein LastSelectedUrgentOrder schmeisst.

    Fertig ist das ganze.

    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:

    ErfinderDesRades:
    Den Artikel den du mir zu studieren empfiehlst, ist genau der Artikel den ich mir angekuckt hab bevor ich meine Frage gepostet hab.
    Hab aber gedacht, der wäre nicht die Antwort auf mein Problem, da ich ja mehrere von diesen Listboxen hab.
    ja, um mehrere Listboxen dran zu binden müsste man modifizieren.
    Also wenn du ein Projekt machst, wo du deine Listboxen so anhängst, wie im Tut gezeigt, dann werden die alle synchron sein, weil hängen alle am selben ChooseView.

    Aber das kannste dann zippen und anhängen, das bastel ich dir eben um.
    Hauptsache ich kann an deine Anwendung erkennen, welche Listbox nach welchem Kriterium gefiltert werden soll.

    ErfinderDesRades schrieb:

    dann werden die alle synchron sein, weil hängen alle am selben ChooseView.

    Ne, er schrieb ja: Ich hab für jede Listbox eine ICollectionView Eigenschaft im VM
    Jede ListBox hat also korrekt seine eigene CollectionViewSource nur eben mit anderen Filtern, Sortierungen usw..
    Wie er schreibt ist der Datentyp der CillectionViewSource.Items immer gleich, somit kann man mittels nur einem Property das zuletzt Selectierte finden. So wie ich geschrieben habe.
    Er soll das mal versuchen, so ist der Lerneffekt eher vorhanden.

    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,
    ​ja stimmt, jede der ListBoxen hat ihre eigene ICollection Eigenschft im VM.
    ​Die verschiedene LB unterscheiden sich nur im Filtern der Daten.

    ​Sacha, dein Tip mit den CurrentChanged Events ist richtig gut. War sehr interessant.
    ​Einen kleinen Haken hat das gaze aber doch!

    ​Sagen wir mal in LBx_1 ist der Erste item angewählt, also in dieser ICollectionView currentItem. Meine Textbox welche mir die Details eines spezifischen "Feldes" anzeigen soll, zeigt mir also die Details des selektierten Items aus LBx_1 an. Wechsle ich jetzt z.B. in LBx_2, und klicke in ein noch nicht vorher aktiviertes Item, dann zeigt mir die gebundene TBx die details des CurrrentItem aus LBx_2 an.
    ​Und jetzt kommt's, klicke ich jetzt wieder auf den Ersten Item der LBx_1, (der ja vorhin schon current Item von LBx_1 war), dann wird das CurrentChanged in LBx_1 nicht "gefeuert".
    ​Meine Details-TextBox zeigt mir noch immer die Details aus LBx_2 an....

    ​Wie es ausschaut komme ich doch nicht an ein Command (wie bei einem Button, wenn das bei einer LBx auch geht...) im XAML des Mainwindows vorbei. Irgendwie wenn die LBx aktiviert werden oder so in der Richtung.

    ​Bevor mir Sacha den Tipp mit dem CurrentChange Event gab, hab ich schon ein paar Stunden damit verbracht, im Internet einen Beitrag zu finden der sich mit LixtBox Selectionchanged, oder sowas Aehnliches in einem MVVM Projekt befasst.... Ohne Erfolg. Und das meiste war ja sowieso in C#. Und das ist mir leider eine totale Fremdsprache....

    ​Ich wäre also sehr dankbar, wenn jemand mir einen Tipp geben könnte.

    Danke,
    ​Jeiss
    Hallo

    Commands bringen dich hier nicht weiter.

    Was ist bitte mit nicht vorher aktiviertes Item gemeint. Ein Item wird nicht aktiviert oder deaktiviert.
    Irgendwas missverstehst du hier.

    Lade doch mal schnell dein PRojekt hoch, dann schau ich mir das gerne an.

    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 Sacha,
    ok ich versuche mal ob ich mein geziptes Projekt hier anhängen kann.

    Falls es dir gelingen sollte, mein Projekt zu starten....Wegen unterschielicher Version, Betriebssytem u.s.w....
    Dann wirst du oben rechts im Fenster meine ListBoxen sehen. In jeder der LB (nur die welche auch Daten enthalten) ist jeweils das erste/obere Item hell-grau.
    Wenn du in der gleichen LB von einem Item zum anderen rüber-klickst, dann wird die TextBox (links im Fenster) auch seinen Text aktualisieren. Klickst du aber auf ein hell-grau gefärbtes Item aus einer ANDEREN LB, dann wird die TB nicht aktualisiert.... :(

    Ok, sag mir ob dir eine Lösung dazu einfällt...

    Ooooppssss...Wie hängt man hier ein Projekt an??
    ​Hat's geklappt?

    Danke im Voraus,
    Jeiss
    Dateien
    ja, du hast da ganz recht - wenn du nur den Focus auf eine Listbox setzst, ohne deren Current zu changen, feuert die CollectionView natürlich auch kein CurrentChanged.

    Was du machen kannst ist, deine Listboxen selbst auf einem ItemsControl anbringen, und das ItemsControl an eine weitere ListCollectionView hängen. Dann sollte's möglich sein, im Viewmodel mitzukriegen, welche Listbox den Focus hat.
    Hallo,
    ​Schön dass du dich so schnell meldest.
    ​Aber leider kann ich so nicht sehr viel mit deinem Vorschlag anfangen. :(

    ​Können wir das vielleicht zusammen ein bisschen zerlegen... :)
    ​Was du machen kannst ist, deine Listboxen selbst auf einem ItemsControl anbringen

    ​Ich nehme ja an , dass das so zu verstehen ist, dass alle meine Listboxen in ein einziges ItemsControl sollen? Oder doch ein ItemsControl pro LB?
    ​und das ItemsControl an eine weitere ListCollectionView hängen

    ​Ok, hab ich mal all die LB in mein ItemsControl, dann muss ich den an eine neue Eigenschaft im VM binden. Richtig?
    ​Welchen Datentyp soll diese neue ListCollectionView den enthalten? Etwa die ListBoxen....?
    ​Ok, ich kuck mir mal an was Google hergibt wenn man "ItemsControl Binding in MVVM" eingibt.

    Danke,
    Jeiss
    ListCollectionViews haben immer Datentyp Object - kannst also reintun was wolle. Oder tu Integers rein. Oder Kartoffeln, oder was du wolle. Oder eben doch Integer. Und im View machste als Integer-DataTemplate eine Listbox hin.
    Und die in ein ItemsControl - das gibts wirklich, das Control. Und das kriegt als ItemspanelTemplate ein horizontales Stackpanel - das müsste gehen.

    Ja, schade, deine Solution ist mit meim 2013 nicht zu öffnen. ah - nochmal probiert - jetzt gehts.

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

    Hi!
    Ich hab ein Job für dich: Visual Studio - Empfohlene Einstellungen
    Ohne das brauchste nicht weiterprogrammieren - Option Strict On Projektweit ist Must-Do-No-Excuses!

    Und ich hab mal einen Haufen Müll aufgeräumt - wirst staunen, wie schlank man programmieren kann! s. Anhang.

    Das eigliche Problem fang ich erst noch an - es ist halt ein entsprechendes Datenmodell zu basteln: Du hast eine Liste mit Listen, also muss das Viewmodel das auch hergeben.
    Dateien

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

    Hallo

    Ich will jetzt nicht auf deinen Code eingehen, habe das projekt auch gleich mal wieder zu gemacht.
    Ich will jetzt nicht wie ErfinderDesRades auf Option StrictOn herumreiten, mir ist auch egal ob es schlenk ist oder nicht, DU musst zurecht kommen, nicht wir.

    Denoch wollte ich mich da jetzt nicht einlesen. Ich habe aber jetzt verstanden was du meinst. Du hast vollkommen recht, das ist ein Problem.
    Ich habe es nun so gelöst das ich das gar kein Event Abonniere sondern das SelectedItem der ListBoxen hernehme und auf ein und das selbe Property in der VM Klasse binde. Und um die tatsache das natürlich kein Item "gechanged" wird nur weil die Listbox den Focus bekommt in den Griff zu bekommen habe ich gebrauch von der Blend.Interactivity gemacht, die nimmt uns die Arbeit am irgendwelche Behaviors programmieren zu müssen. Du warst da ja eh am richtigen weg.
    Wenn die Listbox den Focus bekommt werfe ich einen Commend und übergeben diesem das SelectedItem der aktuell Focusierten Listbox.

    Anbei ein Beispiel.

    Grüße
    Sascha
    Dateien
    • ListBoxTest.zip

      (276,93 kB, 167 mal heruntergeladen, zuletzt: )
    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. ##

    Jo, ich hab auch gebastelt.
    Aber hab die Vorlage voll-überarbeitet.
    Zuerst das Datenmodell - die Initialisierung war ganz falsch, über-länglich-unleserlich - Mittels Sub New() deutlich verkürzt nun so:

    VB.NET-Quellcode

    1. Public Enum WorkCenter : Kart : Cortini_1 : Cortini_2 : Cortini_3 : Tour_Haas : Mac : Fraiseuse : Compression : End Enum
    2. Public Class UrgentOrder
    3. Public Shared MockData As New ObservableCollection(Of UrgentOrder) From {
    4. New UrgentOrder(WorkCenter.Cortini_1, 9338054, "CTBB 25,400 (1'') G10 SNCB5", "bla-bla-Bla", #1/26/2018#) With {.ArticleNbr = 12214367, .NbrPieces = 250},
    5. New UrgentOrder(WorkCenter.Kart, 9338073, "CTBB 28,570 (1 1/8'') G10 SNCB5", "Nouveau délais", #1/26/2018#) With {.ArticleNbr = 12214382, .NbrPieces = 250},
    6. New UrgentOrder(WorkCenter.Cortini_2, 9392592, "Keramik-Walze 5667-5-082603 SNC1", "8 anneaux à livrer", #12/12/2018#) With {.ArticleNbr = 12240356, .NbrPieces = 8},
    7. New UrgentOrder(WorkCenter.Cortini_1, 9416729, "SAPA PRECISION TUBING n.v. ", "Sliptechink", #12/24/2018#) With {.ArticleNbr = 12172036, .NbrPieces = 4},
    8. New UrgentOrder(WorkCenter.Cortini_2, 9423407, "WNGX 080416TN-020D-C (98291) roh CTN3105", "Annullé", #1/23/2018#) With {.ArticleNbr = 12170685, .NbrPieces = 240},
    9. New UrgentOrder(WorkCenter.Kart, 9414089, "CTBB 10,500 EGO SNCB5", "Billes Fritsch, encore 2 partielles à livrer", #1/19/2018#) With {.ArticleNbr = 6291400, .NbrPieces = 525},
    10. New UrgentOrder(WorkCenter.Cortini_3, 9445522, "SNNX 120716TN-020D-C roh CTN3105", "Passer en rohling", #3/16/2018#) With {.ArticleNbr = 12170682, .NbrPieces = 800}}
    11. Public Sub New(workCenter As WorkCenter, orderNr%, matDescript$, remIpc$, confirmDate As Date)
    12. Wkc = workCenter : OrderNbr = orderNr : MaterialDescription = matDescript : RemarquesIPC = remIpc : DateConfirm = confirmDate
    13. End Sub
    14. Public Property OrderNbr As Integer
    15. Public Property ArticleNbr As Integer
    16. Public Property NbrPieces As Integer
    17. Public Property MaterialDescription As String
    18. Public Property RemarquesIPC As String
    19. Public Property DateConfirm As Date
    20. Public Property Wkc As WorkCenter
    21. Public Property Customer As String
    22. End Class

    Dann habich ja gesagt, es handelt sich um eine Liste von Listen - und die Listen zeigen Touren an, und es gibt soviele Touren, wie das Enum WorkCenter Elemente hat.
    Genau das - Klasse WorkCenterTour - habich implementiert:

    VB.NET-Quellcode

    1. Public Class WorkCenterTour
    2. Public Shared ReadOnly MockData As New ObservableCollection(Of WorkCenterTour)
    3. Shared Sub New()
    4. For Each enm As WorkCenter In [Enum].GetValues(GetType(WorkCenter))
    5. MockData.Add(New WorkCenterTour(enm))
    6. Next
    7. End Sub
    8. Public Sub New(wc As WorkCenter)
    9. Me.WC = wc
    10. TourView = New ListCollectionView(UrgentOrder.MockData) With {.Filter = Function(obj As Object) CType(obj, UrgentOrder).Wkc = wc}
    11. End Sub
    12. Public Property WC As WorkCenter
    13. Public Property TourView As ListCollectionView
    14. End Class
    WorkCenterTour.MockData ist eine Liste von WorkCenterTouren - nämlich so viele, wie WorkCenter Enum-Member hat (lines #6 - #8).
    Und eine WorkCenterTour enthält viele UrgendOrders - nämlich UrgendOrder.MockData, aber gefiltert mit dem gewünschte ListCollectionView-Filter (#12).
    Ist eiglich nicht viel Code, odr?

    Und das Mainmodel erstmal - das muss ja nur noch eine Liste halten, und deren CurrentChanges verarbeiten - und die CurrentChanges der Listen in der Liste - alles ein Abwasch:

    VB.NET-Quellcode

    1. Public Class MainViewModel
    2. Implements INotifyPropertyChanged
    3. Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
    4. Public WithEvents WorkspaceTours As New ListCollectionView(WorkCenterTour.MockData)
    5. Public Sub New()
    6. For Each wct In WorkCenterTour.MockData
    7. AddHandler wct.TourView.CurrentChanged, AddressOf CollectionView_CurrentChanged
    8. Next
    9. End Sub
    10. Private Sub CollectionView_CurrentChanged(ByVal sender As Object, ByVal e As EventArgs) Handles WorkspaceTours.CurrentChanged
    11. Dim wct = WorkCenterTour.MockData(WorkspaceTours.CurrentPosition)
    12. SelectedUrgentOrder = DirectCast(wct.TourView.CurrentItem, UrgentOrder)
    13. End Sub
    14. Private _selectedUrgentOrder As UrgentOrder
    15. Public Property SelectedUrgentOrder() As UrgentOrder
    16. Get
    17. Return _selectedUrgentOrder
    18. End Get
    19. Set(ByVal value As UrgentOrder)
    20. If _selectedUrgentOrder Is value Then Return
    21. _selectedUrgentOrder = value
    22. OnPropertyChanged()
    23. End Set
    24. End Property
    25. Private Sub OnPropertyChanged(<Runtime.CompilerServices.CallerMemberName> Optional prop As String = "")
    26. RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(prop))
    27. End Sub
    28. End Class
    Viewmodel feddich.

    War auch im Window1 schnell angezeigt - nur sehr lange hats gedauert, der lbWorkCenters mittels Templates & Styles abzugewöhnen, wie eine Listbox auszusehen.

    XML-Quellcode

    1. <Window x:Name="window" x:Class="Window1" [...] >
    2. <[...]>
    3. <Grid>
    4. <Grid.RowDefinitions>
    5. <RowDefinition Height="auto"/>
    6. <RowDefinition />
    7. </Grid.RowDefinitions>
    8. <DockPanel Grid.Row="0" Background="Wheat">
    9. <TextBlock FontSize="20" Text="Remarques délais:" DockPanel.Dock="Top" />
    10. <TextBlock Text="{Binding WorkspaceTours.CurrentItem.WC, Mode=OneWay}" DockPanel.Dock="Top" />
    11. <TextBox Text="{Binding SelectedUrgentOrder.RemarquesIPC}" TextWrapping="Wrap" AcceptsReturn="True" />
    12. </DockPanel>
    13. <ListBox x:Name="lbWorkCenters" ItemsSource="{Binding WorkspaceTours}" Grid.Row="1">
    14. <ItemsControl.ItemsPanel>
    15. <ItemsPanelTemplate>
    16. <WrapPanel Orientation="Horizontal" Width="{Binding ActualWidth, ElementName=lbWorkCenters, Mode=OneWay}" HorizontalAlignment="Left" />
    17. </ItemsPanelTemplate>
    18. </ItemsControl.ItemsPanel>
    19. <ItemsControl.ItemContainerStyle>
    20. <Style TargetType="ListBoxItem">
    21. <Setter Property="Template">
    22. <Setter.Value>
    23. <ControlTemplate>
    24. <ContentPresenter Content="{Binding Mode=OneWay}" >
    25. <ContentPresenter.ContentTemplate>
    26. <DataTemplate>
    27. <DockPanel>
    28. <TextBlock Background="Wheat" Text="{Binding WC, Mode=OneWay}" DockPanel.Dock="Top" Padding="3" />
    29. <ListBox ItemsSource="{Binding TourView}" GotFocus="UiElement_GotFocus" FontSize="12.5">
    30. <ItemsControl.ItemTemplate>
    31. <DataTemplate>
    32. <StackPanel MaxWidth="190">
    33. <TextBlock Foreground="DarkGreen" TextWrapping="Wrap" Padding="3">
    34. <Run Text="{Binding Path=OrderNbr,StringFormat={}OF: {0}\,}"/>
    35. <Run Text="{Binding Path=ArticleNbr,StringFormat={}Art.: {0}\,}"/>
    36. <Run Text="{Binding Path=NbrPieces,StringFormat={}{0}x}"/>
    37. <LineBreak/>
    38. <Run Text="{Binding Path=MaterialDescription}"/>
    39. </TextBlock>
    40. <DatePicker SelectedDate="{Binding DateConfirm}" HorizontalAlignment="Right" MaxWidth="120"/>
    41. </StackPanel>
    42. </DataTemplate>
    43. </ItemsControl.ItemTemplate>
    44. </ListBox>
    45. </DockPanel>
    46. </DataTemplate>
    47. </ContentPresenter.ContentTemplate>
    48. </ContentPresenter>
    49. </ControlTemplate>
    50. </Setter.Value>
    51. </Setter>
    52. </Style>
    53. </ItemsControl.ItemContainerStyle>
    54. </ListBox>
    55. </Grid>
    56. </Window>

    Und ich musste auch das GotFocus-Event handeln - habich im Codebehind gemacht - mittm Interaction-Geraffal und der Nuget-Abhängigkeit werd ich nicht recht warm:

    VB.NET-Quellcode

    1. Public Class Window1
    2. Private _PrevFocused As DependencyObject
    3. Private Sub UiElement_GotFocus(sender As Object, e As RoutedEventArgs)
    4. 'selectiert das ListboxItem, wo das fokussierte UIElement drin ist - funzt mit alle UiElemente, die auf eim ListboxItem liegen
    5. Dim p = DirectCast(sender, DependencyObject)
    6. If p Is _PrevFocused Then Return
    7. _PrevFocused = p
    8. While Not TypeOf p Is ListBoxItem
    9. p = VisualTreeHelper.GetParent(p)
    10. End While
    11. DirectCast(p, ListBoxItem).IsSelected = True
    12. End Sub
    13. End Class
    Dabei habich festgestellt, dass GotFocus viel zu oft gefeuert wird, weil das ist ein upBubbling Event - also wenn innerhalb der Listbox ein Item gewechselt wird, feuert die Listbox es auch - obwohl ihr Focus ja garnet wechselt (nur ein Item darin).
    Das fange ich ab in line#8

    Das ist übrigens blitzsauberes Codebehind, weil es ist im View, empfängt ein View-Event, und agiert auch nur im View - nicht im Viewmodel.



    Jo - ist jetzt eiglich ein komplettes Tutorial geworden - stecken jede Menge Tricks drinne - kann alles garnet initial besprochen werden (allenfalls auf Fragen) - vlt. sollte ichs in' SourceCode-Austausch packen.

    :)
    Dateien

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

    ErfinderDesRades schrieb:

    mittm Interaction-Geraffal und der Nuget-Abhängigkeit werd ich nicht recht warm

    Solltest aber, biete sehr viele möglichkeiten viel code zu sparen. Klar kann man Dinge welche nur die VIEW angehen ins CodeBehind geben, ist ja nicht weiter schlimm.
    Ich arbeite gerne mit den dlls von Blend, sind sehr schnell und leicht anzuwenden. Und ich benötige gar keinen CodeBehind, was im Team mit einem Designer von großem vorteil ist.
    Weiters kann man den Trigger auch auf ein Template/Style anwenden, was man mit CodeBehind nicht kann.

    Grüße
    Sascha

    PS: @ErfinderDesRades Na, wirst du warm mit der WPF?
    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 ErfinderDesRades und Nofear23m,
    ihr gebt euch ja ganz schön Mühe. Danke! :thumbup:

    @ErfinderDesRades
    Ja ich werde meine Hausaufgaben machen, will ja auch von den "Deppen-Einstellungen" weg.....
    Ich muss zugeben, du hast in der Tat ganz schön aufgeräumt... :)
    Mir ist diese "kompakte" Art der Programmierung noch ziemlich fremd, aber irgendwann muss ich mich ja wohl damit befassen. Warum also nicht gleich...
    Du hast ja schon angekündigt, dass du auch noch das Datenmodell "zurechtschnibbeln" willst. Das Angebot nehme ich natürlich gerne an.

    Ich nehme ja an, dass das nicht viel an der Sache ändern wird. Aber ich wollte dir trotzdem lieber Bescheid sagen, dass es sich bei diesem Projekt nicht bloß um ein "Experiment" zu Uebungszwecken handelt, sondern, dass ich mir erhoffe, dass ich später dank meiner kleinen App,besser den Überblick über meine Arbeit behalten kann.
    Damit will ich nur sagen, dass in einer zweiten Fase, wenn das mit den Listboxen mal fehlerfrei funktioniert, die Daten dann keine Dummydaten mehr sein werden. Sondern aus der großen Listbox (die mit dem schönen hell-grünen Hintergrund) stammen werden.
    Diese grosse LB wird mit Daten aus einer Excel-Datei gespeist. Und wenn alles klappt möchte ich später mal in der Lage sein, eine selektierte Zeile von der gossen LB in eine der oberen Listboxen verschieben zu können. (am liebsten per Drag/Drop...wäre praktisch!)
    Aber wie gesagt, wollte nur dass du es weist. Ändert ja aber wohl nichts an dem Datenmodell das du mir noch zeigen möchtest. Es geht hier ja nur um die Funktionsweise.
    Ich werde dein Modell später ja bestimmt an meine "urgent orders" anpassen können.
    Aber die Eigenschaften welche jetzt schon in der Dummy-Klasse verwendet werden, die findet man ganz bestimmt später auch in der fertigen App zurück.

    @Nofear23m
    Hab mir natürlich auch deinen "ListBoxTest" angeschaut. Funktioniert auch einwandfrei.
    Muss mir das aber nochmal genauer angucken.
    Die Bindung von SelectedItem an die LastSelectedCar Eigenschaft leuchtet mir ja auch ein.
    Aber die EventTrigger auf GotFocus in Verbindung mit den Commands, das muss ich noch ein bisschen "studieren".
    Blöde Frage:
    Geht das mit einem gewöhnlichen Visual Studio 2015, oder so? Oder brauch man da "Hilfsmittel"? Hab da an Blend gedacht, weil du ja in deiner letzten Antwort "Blend.Interactivity" erwähnst. Kenn das leider noch nicht :(

    Auf jeden Fall bedanke ich mich bei euch für die Unterstützung. Und ich freue mich jetzt schon auf das fertig Ergebnis (in ein paar Monaten...)
    Aber dank eurer Hilfe kommt es in Reichweite. Danke.
    Jeiss

    ​Oooppsss....! wie schnell seid ihr denn?
    ​Meine Antwort passt jetzt nicht mehr zu 100%...
    ​Aber macht nichts.... Ich hoffe ihr versteht was ich gemeint hab. Sorry.
    ​Jeiss

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

    Jeiss schrieb:

    Mir ist diese "kompakte" Art der Programmierung noch ziemlich fremd, aber irgendwann muss ich mich ja wohl damit befassen. Warum also nicht gleich...
    ich lege großen Wert auf Kompaktheit.

    Guck dir mein MainViewmodel an und deines: Bei meim sieht man das komplette Model auf einem Blick - es ist eiglich keine Zeile dabei, die nicht unmittelbar verständlich ist.
    Nu gugge deines: Da sieht man garnix.
    Nur zusammengeklappte Regions.
    Da kann man dann herumklappen und rauf- und runter-scrollen in Hoffnung iwann einen Verständnis-Ansatz zu finden, dem man nachgehen kann.
    Und natürlich schmuggeln sich da 100 mal leichter Fehler ein.
    Es gibt ein total wichtiges Programmierprinzip: DRY: "Dont Repeat Yourself".
    Wenn man das ernst nimmt, dann ärgert man sich über jede vb.net-Property, weil da über mindestens 6 Zeilen immer dasselbe steht.
    Das ist auch der Grund, warum MS AutoProps eingeführt hat - nämlich genau DRY.
    Aber AutoProps können halt kein NotifyPropertyChanged, und da ist man wieder beim Ärgern.

    Und von Regions halt ich auch nix. Ich will Code sehen, nicht verstecken.
    Code, den man nicht zu sehen braucht (etwa die NotifyPropertyChanged-Logik) kann man meist auslagern - und gewinnt dabei auch noch Wiederverwendbarkeit.

    Oder es bleibt unaufgeräumter Müll inne Regions liegen, grad über den muss man stundenlang nachdenken, um ihn zu verstehen - bis einem dämmert: das Verstehen ist deshalb schwierig, weil geht garnicht, weil: der Code ist sinnlos.
    Dieses SapOrdersView zB - was hats damit auf sich? (rethorische Frage - ich wills garnet wissen)



    Jeiss schrieb:

    ... Daten dann keine Dummydaten mehr sein werden...

    Thema Mocking
    Mocking ist ein Prinzip inne Wpf. Es werden zur Designzeit generierte Mockdaten bereitgestellt - zur Laufzeit werden aber richtige Daten geladen. Da gibts Standard-Vorgehensweisen für, bzw. jeder legt sich was dafür zurecht - habich hier aber nicht gemacht, aber das wird natürlich kommen müssen.
    Bei NoFear siehste übrigens iwo eine Methode IsInDesignMode - oder so - das ist sowas zur Mocking-Unterstützung.
    Weil zum Mocking muss die Wpf ja zuallererst unterscheiden können, ob sie nur im Designer läuft oder richtig.



    Und noch ein:

    Jeiss schrieb:

    ... Daten dann [...] aus der großen Listbox [...] stammen werden.
    Komm mir nicht mit sowas! - nie wieder!
    Daten kommen nicht aus Listboxen - schlag dir das aus Kopf, und zwar tüchtig!