DataBinding mit einem TabControl auf einem untergeordnetem Fenster
- WPF
Sie verwenden einen veralteten Browser (%browser%) mit Sicherheitsschwachstellen und können nicht alle Funktionen dieser Webseite nutzen.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Hier erfahren Sie, wie einfach Sie Ihren Browser aktualisieren können.
Es gibt 47 Antworten in diesem Thema. Der letzte Beitrag () ist von Nofear23m.
-
-
Hallo
Da gibt es mehrere Möglichkeiten. MVVM verbietet ja jetzt nicht explizit CodeBehind. Also könntest du theoretisch beim Button_click das Fenster schliessen und auch im ViewModel den Savecomand ausführen.
Gibt aber auch die Möglichkeit über sauberes MVVM.
Du hast ja ein Window als MyWindow.xaml. Dieses weis das es IMMER eine IWindowVm bekommen wird. Du könntest ja in die IWindowVM Schnittstelle einEvent CloseWindow
hineinpacken.
Im MyWindow packst du dann im Loaded Event einAddHandler
ein und machst das Fenster zu.
Richtig sauber und komfortabel geht das über Messages. Wo sich Fenster, Usercontrols usw. die Nachrichten Abonnieren und du im VM ohne Events die Nachricht wirfst. Das geht sogar mit Parametern die man übergeben kann.
Hierfür würde ich aber einen neuen Thread aufmachen.
Ich mache es nur über Messages. Kann ich dir gerne zeigen wenn Interesse vorhanden.
Grüße
Sascha
PS: Freut mich das dieses Thema mal wem interessiert. Wird zu selten behandelt.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. ##
-
ich hab mir NoFear23's Code nur in einer jetzt "veralteten" Version angeguckt - wäret ihr beide daran interesssiert, zu erlernen, wie man den Wpf-Designer stärker als wirklichen Designer nutzen kann?
Dann würde ich mir die neueste NoFear23-Version mal vorknöpfen und versuchen, umzufrickeln.
Ich bau dann allerdings auch Option Strict On ein, und schmeisse den Microsoft.Visualbasic-Namespace raus.
Also worauf ich hinaus wollen würde sind 2 Dinge: Visual Studio - Empfohlene Einstellungen
und Grundlagen - MVVM: "Binding-Picking" im Xaml-Editor
Aber wäre einiges an Arbeit für mich... -
Hi,
gerne.
Option strict ist doch on? Genauso wie der Namespace zwar angehakt ist aber fast nicht benutzt wird. Zumindest sind mir beim kopieren in das andere Projekt, welches beides berücksichtigt keine Fehler aufgefallen.
Edit: habe alles mal im Projekt hier umgestellt, es sind kaum bzw. keine Fehler. Diese habe ich aber bereits hier angesprochen.
Auf das Binding-Picking welches du in deinem Therad ansprichst wollte ich die ganze Zeit hinaus. -
Hallo
wäret ihr beide daran interesssiert, zu erlernen, wie man den Wpf-Designer stärker als wirklichen Designer nutzen kann?
Na auf jeden Fall. Bin IMMER für was neues.
Ich weis nur nicht ganz was Ihr mit dem Binding-Picking meint. Das ist doch das Quadrat im PropertieWindow wo man draufklickt und das Binding holen kann. Funzt doch wunderbar sobald man den DesignTime DataContext festlegt.
Wobei ich sagen muss, persönlich tippe ich immer. Wenn der DesignTime Context drinnen ist habe ich ja auch IntelliSense, bin ich meist schneller als mit dem "Picking".
Die Visual Basic verweise habe ich bei mir bereits entfernt, hatte ich total übersehen und waren leider ein Überbleibsel. Danke hierfür nochmals an @SKeks.
Aber nur her damit, immer gut was neues zu lernen, ob ichs dann verwende kann ich nicht sagen, aber ich bin immer offen für neues.
Grüße
SaschaIf _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. ##
-
SKeks schrieb:
Option
strict ist doch on?
Nofear23m schrieb:
Ich weis nur nicht ganz was Ihr mit dem Binding-Picking
meint.
und mal ins Video reingugge.
Nofear23m schrieb:
Das ist doch das Quadrat im PropertieWindow wo man draufklickt und das
Binding holen kann. Funzt doch wunderbar sobald man den DesignTime
DataContext festlegt.
Jo dann war das veraltete wohl wirklich veraltet.
Weil was ich mir angeguckt hab, da war Strict Off, und BindingPicking war nicht möglich (kein d:DataContext gesetzt).
Ok - jetzt das aktuelle angeguckt: In 2 von 3 Projekten ist Strict Off und in 3en ist MVB general-importiert - also soo alles paletti scheints mir doch nicht.
Aber mein akt. Hauptproblem ist, dass mir scheints 2 Dateien fehlen:
Error 1 Unable to open module file 'C:\Users\Account2\Downloads\MVVM_DEMO_Neu_Trigger\Demo.Views\BoolView.xaml.vb': Das System kann die angegebene Datei nicht finden. C:\Users\Account2\Downloads\MVVM_DEMO_Neu_Trigger\Demo.Views\BoolView.xaml.vb 1 1 Demo.Views
Error 2 Unable to open module file 'C:\Users\Account2\Downloads\MVVM_DEMO_Neu_Trigger\Demo.Views\IntView.xaml.vb': Das System kann die angegebene Datei nicht finden. C:\Users\Account2\Downloads\MVVM_DEMO_Neu_Trigger\Demo.Views\IntView.xaml.vb 1 1 Demo.Views
-
diese beiden Dateien kannste löschen.Dies sind Überbleibsel aus den Iterationen.
MVB raus ergibt einen Fehler im RelayCommand bei der Prüfung auf "nothing" und "Option Strict" On müsste Fehler bei den Modalen Dialogen ergeben, wenn mich nicht alles täuscht. Die Subs, die bei der Umstellung einen Fehler ergeben kann man hier auskommentieren. Das meinte ich damit.
Zuletzt muss noch das Startprojekt auf die MyWindowsApp gelegt werden. -
-
ErfinderDesRades schrieb:
Deswegen gab ich doch den Link - musste halt auch folgen,
und mal ins Video reingugge.
Habe ich, Danke. Ich weis das man Links folgt. Genau deshalb war ich verwirrt, da wir das ja drin hatten. Aber das war nicht die Fragestellung weshalb ich es beim ersten Beispiel nicht eingebaut hatte.
Man muss ja niemanden gleich mit Infos erschlagen oder?
Du musst dir hald das letzte Beispiel herunterladen. Also, was funzt in diesem Model jetzt nicht?
also soo alles paletti scheints mir doch nicht
Wenn wir jetzt die i Tüpfelchen anfangen rauszupicken, von einem Anschauungsbeispiel dann muss ich sagen. Danke. Das mit Strict On ist klar. Kein Problem das zu ändern.
Wolltest du jetzt nur Fehler suchen oder uns was zeigen? Wenn letzteres dann gerne. Bin immer für neues und lerne gerne dazu.
Vielleicht hast du einen anderen Ansatz. Wäre cool, denn ich hab mir auch nur alles zusammengesucht und das rausgenommen was ich für gut empfunden habe. Wenn es besser geht freue ich mich SEHR. Wäre ja cool.
Schöne Grüße
SaschaIf _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. ##
-
naja, was zeigen.
Aber dazu nicht unbedingt erst alle Fehler berichtigen müssen.
Aber ich sehe auch nicht, dass im Xaml irgendwo ein d:DataContext festgelegt wäre, dabei habe ich inzwischen die neueste Version am Wickel, also aus post#18
Ah - jetzt doch noch gefunden - im Demo-Views-Projekt.
Also ich guggemol weiter...
-
Also ich guggemol weiter
Top !
Freu mich, bin immer offen für Vorschläge wie es besser geht, oft sieht man ja den Wald vor lauter Bäumen nicht.
PS: Sollen wir hierfür einen neuen Thread machen??
Grüße
SaschaIf _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. ##
-
Nicht zerfleischen bitte
Im Anhang das Projekt mit Strict On und ohne VB-Namespace. Messageboxen sind nun auskommentiert, also funktionieren auch die beiden SpeichernButtons nicht mehr
Edit: Oder man formuliert den Rückgabetyp beim Dialog alsNullable(of Boolean)
. dann kann man alles einkommentiert lassen:
VB.NET-Quellcode
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „SKeks“ ()
-
SKeks schrieb:
Oder man formuliert den Rückgabetyp beim Dialog als Nullable(of Boolean)
Oder man baut den Enumerator einfach nach wie ich es mitEnuMessageBoxResult
oderEnuMessageBoxButton
oder mitEnuMessageBoxImage
gemacht habe. Ist am saubersten.
Grüße
SaschaIf _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. ##
-
Also ich hab jetzt mal eine ich finde aufs nötige reduzierte Version gemacht - 15 Dateien in 3 Projekten auf nur 5 in einem reduziert - Infrastruktur bei der Zählung nicht berücksichtigt.
Erkennbar ist auch das Designtime-Daten-Feature, das geht noch bisserl weiter als "nur" BindingPicking.
Auch hab ich ein bischen logische Logik ans SaveCommand gemacht, also da wird die aktuelle Person nu tatsächlich einer Liste zugefügt, und sieht man auch.
Insgesamt ist das Beispiel ja ziemlich weltfremd, also dass da Personen erzeugt werden, in nicht-modalen Fenstern zur Bearbeitung angezeigt, und wenn man Fenster schließt, sind sie weg...
Und dann muss man sich drum kümmern, dass nicht mehrere Personen gleichzeitig geöffnet werden - solch würde man normalerweise wohl einfach mit modalen Dialoge abhandeln...
In Grundlagen - MVVM-Anwendungs-Struktur hab ich was gemacht, wo man Personen editieren, zufügen, löschen kann - also was man normal von einer Datenverarbeitung erwartet.
Edit: Dateianhang siehe jetzt post#39Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von „ErfinderDesRades“ ()
-
Hallo
Danke für die mühe.
Ich fang mal so an wie ich die Files geöffnet habe.
1.) NotifyPRopertyChanged- Warum ICloneable implementieren? Mir ist klar was ich damit machen kann. Aber: Habe ich jetzt einen Denkfehler. Die RelayCommand Schnittstelle hat keinen Parameterlosen, somit kann keine VM Klasse welches ein RelayCommand verwendet kopiert werden oder? fände ich cool wenn das ginge. Ich bilde mir ein das ich da mal gegen eine Wand gelaufen bis, kann aber sein das ich das jetzt verwechsle.
- Wozu PropIfDifferent? Wo liegt der Vorteil. Schon klar. Wenn der Wert gleich ist muss nicht die View aktualisieren. Sonst noch was?
- Auf Serializable gehe ich jetzt nicht weiter ein. Ist klar was es tut.
- Was ich interessant finde. Das
IsInDesignMode
Property. So hatte ich das noch nicht gesehen, erkenne natürlich auch die Vorteile. Ich habe es immer mitDesignerProperties.GetIsInDesignMode(DependancyObject)
gelöst. Damit war ich aber nie zufrieden da es ja einen Verweis auf System.Windows benötigt wegenDependencyObject
. Das ist elegant gelöst. Muss ich mal probieren. - MockDesignMode verwendest du dann für UnitTests richtig??
2.) Mainmodel (Eigentlich ja MainViewModel)Private WithEvents wndPerson As Window
hat in einem ViewModel nix zu suchen!!- Wenn du schon so genau bist das du meinst man muss einen Kunden speichern obwohl das nicht di efrgestellung war und nix mit dem Pattern zu tun hat dann bitte im RelayCommand auch CanExecute vergeben. Speichern OHNE Kundendaten darf nicht möglich sein. (Du hast angefangen)
Private Sub wndPerson_Closed(sender As Object, e As EventArgs) Handles wndPerson.Closed
Oh mein Gott.
Der Rest ist soweit eigentlich so wie ich es habe. Nur das ich das öffnen und schliessen von Fenstern sowie spezialle dinge mit Controls oder Views wo binden nicht möglich ist oder wo gewisse Dinge angestoßen werden müssen über ein MessageSystem mache. Da hat sich das dann auch erledigt. Sehr komfortabel.
Das kannst du dir mal ansehen:
Spoiler anzeigen VB.NET-Quellcode
- Imports System.Reflection
- ''' <summary>
- ''' Provides loosely-coupled messaging between
- ''' various colleague objects. All references to objects
- ''' are stored weakly, to prevent memory leaks.
- ''' </summary>
- Public Class Messenger
- #Region "Constructor"
- Public Sub New()
- End Sub
- #End Region
- #Region "Register"
- ''' <summary>
- ''' Registers a callback method to be invoked when a specific message is broadcasted.
- ''' </summary>
- ''' <param name="message">The message to register for.</param>
- ''' <param name="callback">The callback to be called when this message is broadcasted.</param>
- Public Sub Register(message As String, callback As [Delegate])
- If String.IsNullOrEmpty(message) Then
- Throw New ArgumentException("'message' cannot be null or empty.")
- End If
- If callback Is Nothing Then
- Throw New ArgumentNullException("callback")
- End If
- Dim parameters As ParameterInfo() = callback.Method.GetParameters()
- If parameters IsNot Nothing AndAlso parameters.Length > 1 Then
- Throw New InvalidOperationException("The registered delegate can have no more than one parameter.")
- End If
- Dim parameterType As Type = If((parameters Is Nothing OrElse parameters.Length = 0), Nothing, parameters(0).ParameterType)
- _messageToActionsMap.AddAction(message, callback.Target, callback.Method, parameterType)
- End Sub
- Public Sub UnRegister(message As String, target As Object)
- _messageToActionsMap.RemoveAction(message, target)
- End Sub
- #End Region
- #Region "NotifyColleagues"
- ''' <summary>
- ''' Notifies all registered parties that a message is being broadcasted.
- ''' </summary>
- ''' <param name="message">The message to broadcast.</param>
- Public Sub NotifyColleagues(message As String)
- If String.IsNullOrEmpty(message) Then
- Throw New ArgumentException("'message' cannot be null or empty.")
- End If
- Dim actions = _messageToActionsMap.GetActions(message)
- If actions IsNot Nothing Then
- actions.ForEach(Function(action) action.DynamicInvoke())
- End If
- End Sub
- ''' <summary>
- ''' Notifies all registered parties that a message is being broadcasted.
- ''' </summary>
- ''' <param name="message">The message to broadcast</param>
- ''' <param name="parameter">The parameter to pass together with the message</param>
- Public Sub NotifyColleagues(message As String, parameter As Object)
- If String.IsNullOrEmpty(message) Then
- Throw New ArgumentException("'message' cannot be null or empty.")
- End If
- Dim actions = _messageToActionsMap.GetActions(message)
- If actions IsNot Nothing Then
- For Each a In actions
- a.DynamicInvoke(parameter)
- Next
- ' actions.ForEach(Function(action) action.DynamicInvoke(parameter))
- End If
- End Sub
- #End Region
- #Region "MessageToActionsMap [nested class]"
- ''' <summary>
- ''' This class is an implementation detail of the Messenger class.
- ''' </summary>
- Private Class MessageToActionsMap
- ' Stores a hash where the key is the message and the value is the list of callbacks to invoke.
- ReadOnly _map As New Dictionary(Of String, List(Of WeakAction))()
- Friend Sub New()
- End Sub
- ''' <summary>
- ''' Adds an action to the list.
- ''' </summary>
- ''' <param name="message">The message to register.</param>
- ''' <param name="target">The target object to invoke, or null.</param>
- ''' <param name="method">The method to invoke.</param>
- ''' <param name="actionType">The type of the Action delegate.</param>
- Friend Sub AddAction(message As String, target As Object, method As MethodInfo, actionType As Type)
- If message Is Nothing Then
- Throw New ArgumentNullException("message")
- End If
- If method Is Nothing Then
- Throw New ArgumentNullException("method")
- End If
- SyncLock _map
- If Not _map.ContainsKey(message) Then
- _map(message) = New List(Of WeakAction)()
- End If
- _map(message).Add(New WeakAction(target, method, actionType))
- End SyncLock
- End Sub
- Friend Sub RemoveAction(message As String, target As Object)
- Try
- SyncLock _map
- Dim weakActions As List(Of WeakAction) = _map(message)
- For i As Integer = weakActions.Count - 1 To -1 + 1 Step -1
- If (weakActions(i)._targetRef.Target Is target) OrElse (TryCast(weakActions(i), WeakAction) IsNot Nothing AndAlso DirectCast(weakActions(i), WeakAction)._method Is target) Then
- weakActions.Remove(weakActions(i))
- End If
- Next
- End SyncLock
- Catch ex1 As KeyNotFoundException
- Debug.WriteLine(ex1.ToString)
- End Try
- End Sub
- ''' <summary>
- ''' Gets the list of actions to be invoked for the specified message
- ''' </summary>
- ''' <param name="message">The message to get the actions for</param>
- ''' <returns>Returns a list of actions that are registered to the specified message</returns>
- Friend Function GetActions(message As String) As List(Of [Delegate])
- If message Is Nothing Then
- Throw New ArgumentNullException("message")
- End If
- Dim actions As List(Of [Delegate])
- SyncLock _map
- If Not _map.ContainsKey(message) Then
- Return Nothing
- End If
- Dim weakActions As List(Of WeakAction) = _map(message)
- actions = New List(Of [Delegate])(weakActions.Count)
- For i As Integer = weakActions.Count - 1 To -1 + 1 Step -1
- Dim weakAction As WeakAction = weakActions(i)
- If weakAction Is Nothing Then
- Continue For
- End If
- Dim action As [Delegate] = weakAction.CreateAction()
- If action IsNot Nothing Then
- actions.Add(action)
- Else
- ' The target object is dead, so get rid of the weak action.
- weakActions.Remove(weakAction)
- End If
- Next
- ' Delete the list from the map if it is now empty.
- If weakActions.Count = 0 Then
- _map.Remove(message)
- End If
- End SyncLock
- Return actions
- End Function
- End Class
- #End Region
- #Region "WeakAction [nested class]"
- ''' <summary>
- ''' This class is an implementation detail of the MessageToActionsMap class.
- ''' </summary>
- Private Class WeakAction
- ReadOnly _delegateType As Type
- Friend ReadOnly _method As MethodInfo
- Friend ReadOnly _targetRef As WeakReference
- ''' <summary>
- ''' Constructs a WeakAction.
- ''' </summary>
- ''' <param name="target">The object on which the target method is invoked, or null if the method is static.</param>
- ''' <param name="method">The MethodInfo used to create the Action.</param>
- ''' <param name="parameterType">The type of parameter to be passed to the action. Pass null if there is no parameter.</param>
- Friend Sub New(target As Object, method As MethodInfo, parameterType As Type)
- If target Is Nothing Then
- _targetRef = Nothing
- Else
- _targetRef = New WeakReference(target)
- End If
- _method = method
- If parameterType Is Nothing Then
- _delegateType = GetType(Action)
- Else
- _delegateType = GetType(Action(Of )).MakeGenericType(parameterType)
- End If
- End Sub
- ''' <summary>
- ''' Creates a "throw away" delegate to invoke the method on the target, or null if the target object is dead.
- ''' </summary>
- Friend Function CreateAction() As [Delegate]
- ' Rehydrate into a real Action object, so that the method can be invoked.
- If _targetRef Is Nothing Then
- Return [Delegate].CreateDelegate(_delegateType, _method)
- Else
- Try
- Dim target As Object = _targetRef.Target
- If target IsNot Nothing Then
- Return [Delegate].CreateDelegate(_delegateType, target, _method)
- End If
- Catch
- End Try
- End If
- Return Nothing
- End Function
- End Class
- #End Region
- #Region "Fields"
- ReadOnly _messageToActionsMap As New MessageToActionsMap()
- #End Region
- End Class
Edit: Achja, und jetzt teile mal das ganze auf. Gib die Views in ein Projekt, das ViewModel in ein Projekt und schau dann mal.
In MVVM soll Das Model, das ViewModel und die View austauschbar sein. Wenn ich jetzt eine MVC Anwendung oder eine Windows 10 App machen will schau ich schön drein wenn ich im ViewModel direkt Fenster anspreche. Das hier:
... ist aus dieser Quelle: msdn.microsoft.com/en-us/library/ff798384.aspx
Schöne Grüße und Danke für den Input, einiges werde ich sicher verwenden.
GrüßeIf _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. ##
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Nofear23m“ ()
-
Nofear23m schrieb:
1.) NotifyPRopertyChanged
Warum ICloneable implementieren? Mir ist klar was ich damit machen kann.
Aber: Habe ich jetzt einen Denkfehler. Die RelayCommand Schnittstelle hat keinen Parameterlosen, somit kann keine VM Klasse welches ein RelayCommand verwendet kopiert werden oder?Overridable
eingebastelt, weil wie ein bestimmtes VM im Einzelnen zu klonen ist - das ist oft nach Bedarf nachzuarbeiten.
Etwa ein RelayCommand ist wohl meist besser vom Klonen auszuschließen.
Der Witz ist wohl das (Protected)MemberwiseClone()
, was da ausgeführt wird. Weil das deckt alleStructure
-Datentypen und zusätzlichString
ab - also wenn man meine Viewmodelse klonen muss hat man deutlich weniger Schreibarbeit.
Wozu PropIfDifferent? Wo liegt der Vorteil. Schon klar. Wenn der Wert gleich ist muss nicht die View aktualisieren. Sonst noch was?
...
MockDesignMode verwendest du dann für UnitTests richtig??
2.) Mainmodel (Eigentlich ja MainViewModel)
Private WithEvents wndPerson As Window
hat in einem ViewModel nix zu suchen!!
Weisst du... überzeugen kannman mich so nicht. Bring Argumente, nenn mir nachvollziehbare gute Gründe. Zeige an einem Beispiel, dasses so nicht geht.
Weil ich habe am Beispiel gezeigt, dass es so geht. Und ich erreiche das Ziel - Re-enablen der Buttons beim Schließen des windows - exorbitant viel einfacher als die Klimmzüge über mehrere Projekte, Viewmodels und Interfaces hinweg, die ich vorgefunden hatte.
Wenn du schon so genau bist das du meinst man muss einen Kunden speichern obwohl das nicht di efrgestellung war...
... dann bitte im RelayCommand auch CanExecute vergeben. Speichern OHNE Kundendaten darf nicht möglich sein.
Aber da kommen wir wohl wieder an die Sicherheits-Philosophie-Diskussion - weisst ja: ich finde es sinnlos und sogar schädlich, gegen Dinge abzusichern die garnicht vorkommen können.
Private Sub wndPerson_Closed(sender As Object, e As EventArgs) Handles wndPerson.Closed
Oh mein Gott.
Der Rest ist soweit eigentlich so wie ich es habe.
Aber zB in dem Punkt hast auch wieder recht: das mit dem BindingPicking hat nicht ganz gefehlt (ich hatte es nur erst ziemlich spät gefunden).
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()
-
Wer sagt das? Du?
Weisst du... überzeugen kann man mich so nicht. Bring Argumente, nenn mir nachvollziehbare gute Gründe.
Nein, ich sage das nicht. Siehe mein Edit. Wie war das mit Links folgen
Weist du. Ich finde es gut wenn mir jemand etwas aufzeigt was ich falsch oder schlecht mach. Aber wenn DU, der immer von sich behauptet das sein Code ach so perfekt ist hier ein Beispiel hochladest wo das ViewModel das View kennt dann muss ich sagen. Gut für dich das es geht, richtig ist es jedoch nicht.
Das MVVM spezifiziert dies. Siehe wieder Link.
Und übrigens: Ich KANN in deinem Beispiel alle Daten aus den Textfelder löschen und auf speichern klicken.
Weiters: Du meinst meine RelayCommand Klasse wäre so schlecht und verwendet auch Is Nothing(obj) in deiner. Oder ist das eh meine. Toll
Ausserdem: Du generierst einen Bindingfehler in deiner Solution:
Spoiler anzeigen System.Windows.Data Error: 7 : ConvertBack cannot convert value '' (type 'String'). BindingExpression:Path=Size; DataItem='PersonVM' (HashCode=21522166); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') FormatException:'System.FormatException: Die Eingabezeichenfolge hat das falsche Format.
bei System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
bei System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
bei System.String.System.IConvertible.ToInt32(IFormatProvider provider)
bei System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
bei MS.Internal.Data.SystemConvertConverter.ConvertBack(Object o, Type type, Object parameter, CultureInfo culture)
bei System.Windows.Data.BindingExpression.ConvertBackHelper(IValueConverter converter, Object value, Type sourceType, Object parameter, CultureInfo culture)'
DU redest immer von Performance: Bindingfehler sind die wohl SCHLIMMSTE Bremse in der WPF. Egal ob diese nun einen Fehler verursachen oder nicht.
Versteh mich bitte nicht falsch, ich hoffe ich darf dich kritisieren wie du auch mich. Du hast gemeint das du uns hier was lernen willst weil unser/mein vorhaben noch viel besser geht. Aber dann zeig uns auch wie es besser geht. Und bitte nicht wie es nicht MVVM konform ist.
Ich hoffe das auch DU Kritik verträgst, austeilen kannst du ja auch.
Fazit: Ich nehme ein bis zwei dinge sicherlich mit, vieles aber nicht und einiges Verurteile ich definitiv.
Grüße
Sascha
PS: Nicht böse sein.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. ##
-
Streitet euch nicht
Eins vorweg ich habe mir keinen Code angeschaut, da ich aktuell kein VS an diesem Rechner habe. Morgen früh dann wieder.
Ich finde die ganze Diskussion interessant vom Gesichtspunkten her, dass ich mir genau vorstellen kann, wie EDR sein Code aussieht Immerhin habe ich WPF mit seinen MVVM Tuts hier im Forum angefangen. Rein pragmatisch her hatte ich es auch so gemacht, Jedoch war dies eben der Stein des Anstoßes, dass das VM die View kennt. Klar ist dies der einfache Weg und er funktioniert, da dieser wie soll ich sagen der naheliegendste ist. Deswegen wollte ich auch den anderen Weg sehen.
Rein Codemäßg und zeilenmäßig ist der pragmatische Weg auch kürzer. Aber bei MVVM gelten halt unter Umständen auch andere Gesichtspunkte.
Das Problem an MVVM und WPF ist, ich habe es bereits angesprochen, dass die Lernkurve sehr flach ist und man viel Wissen über viele verschiedene Dinge benötigt (Binding, templates, Styles, VM, ....) um es richtig anzuwenden. Leider ist diese Forumssektion teilweise wie tot im Gegensatz zu der "Sonstige Problemstellungen" in der aber leider viel WinForms abgehandelt wird.
Wenn man sich das Ganze selbst beibringt muss man also auf sein Google-Fu zurückgreifen und landet oft halt bei StackOverflow. Dort wird aber viel mit Codebehind oder programmatisch gelöst statt die Features von WPF zu nutzen. unabhängig davon sind halt auch mittlerweile viele Beiträge schon x Jahre alt und beziehen sich auf sehr alte Frameworks.
Schlußendlich bleibt es jedem selbst überlassen wie er Problemstellungen löst, vor allem wenn es privater Code ist. Jedoch ist es nie verkehrt auch neben dem Tellerrand zu schauen. Ich für meinen Teil kann sagen, dass bei mir niemals die View ausgetauscht wird. Oder sich das Viewmodel ändert. Trotzdem ist es sicher nicht verkehrt das "richtige" Trennen vom VM, V und M zu lernen. Vielleicht bringt es ja irgendwann mal etwas. Man weiß ja nie wohin man sich (auch beruflich) entwickelt.
MVVM ist ja kein Dogma. Was mir zum Beispiel an Nofear23m Code danfangs Probleme bereitet hat, ist dieses verzetteln von Code. Klar muss die View für sich entscheiden wie sie was rendert, aber ich hätte das trotzdem gerne zentral gesammelt wie zum Beispiel in Application.Ressources. Wenn ich über das VM sagen kann welches Control genutzt wird warum ein weiteres Lay einführen?
@Nofear23m kannst du das mit den Messages näher ausführen? Anwendung und Nutzen? Ich kann leider aus deinem Code ndas nicht rauslesen.
Das Beispiel von mir war natürlich realitätsfern. Es sollte nur aufzeigen, dass ich ein VM auf 2 Fenstern bearbeiten möchte und dass eine Trennung auf 2 VM eben nicht geht, da diese auf die gleiche Instanz des VM zurückgreifen. Dass ein Speichern von personen nicht geht oder sonst wie nicht ganz ausgereift ist, war mir klar und nicht meine Intention
Gruß -
SKeks schrieb:
Streitet euch nicht
Ich will aber!!
@Nofear23m:
Sry - den Edit nicht gesehen - da siehste mal wie lange ich für sone Antwort brauche
Ja, MS sagt, das ist nicht MVVM, was ich verzapfe.
Aber damit ist mir immer noch nicht gezeigt, was nun ein Problem damit ist, und welche Lösung besser ist. Deine Lösung findich nicht besser, weil ist vielfach komplizierter und äusserst undurchschaubar.
Nofear23m schrieb:
Und übrigens: Ich KANN in deinem Beispiel alle Daten aus den Textfelder löschen und auf speichern klicken.
Ach du meintest eine Validierung der Eingaben des vorhandenen Datensatzes? - ja - habich nicht dran gedacht - genau wie du!
Komisch - den BindingFehler kriege ich nicht.
Nofear23m schrieb:
Du meinst meine RelayCommand Klasse wäre so schlecht
Kann mich nicht erinnern, das gesagt zu haben. Wenn doch, nehm ich das auf jeden Fall zurück. Jdfs. in meiner Variante hab ich das RelayCommand von dir übernommen (meins ist viel komplizierter (und für dieses Beispiel garnet besser)).
Ups - jetzt guck ichs erstmalig an, und musses jetzt doch sagen: Dein RelayCommand geht so nicht:VB.NET-Quellcode
- Public Custom Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
- AddHandler(value As EventHandler)
- If IsNothing(_canExecute) = False Then
- AddHandler CommandManager.RequerySuggested, value
- End If
- End AddHandler
- RemoveHandler(value As EventHandler)
- If IsNothing(_canExecute) = False Then
- AddHandler CommandManager.RequerySuggested, value
- End If
- End RemoveHandler
- RaiseEvent(sender As Object, e As EventArgs)
- End RaiseEvent
- End Event
Ach - und bei RaiseEvent erfolgt ja gar keine Aktion!
Also da mach ich jetzt doch mal hin, wie ich gelernt hab, dass muss:VB.NET-Quellcode
- Public Custom Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
- AddHandler(value As EventHandler)
- AddHandler CommandManager.RequerySuggested, value
- End AddHandler
- RemoveHandler(value As EventHandler)
- RemoveHandler CommandManager.RequerySuggested, value
- End RemoveHandler
- RaiseEvent(sender As Object, e As EventArgs)
- CommandManager.InvalidateRequerySuggested()
- End RaiseEvent
- End Event
ICommand.CanExecuteChanged
ist schon sehr eigenartig.
Iiieh!
Da ist ja der MVB-Namespace in meiner eigenen Solution!
Sofort alles löschen und neu aufnehmen (Dateianhang)!
...Beispiel ... ein VM auf 2 Fenstern bearbeiten möchte und dass eine Trennung auf 2 VM eben nicht geht, da diese auf die gleiche Instanz des VM zurückgreifen.
Sowohl Bindingpicking als auch Option Strict (meine ursprünglichen Anliegen) waren zumindest teilweise bekannt.
Und meine Lösung, um dassselbe VM mit verschiedenen Views anzuzeigen ist bodenlos trivial und verstößt gegen MVVM.
Was für mich ja keine heilige Kuh ist - ich verstoße halt ganz unverfroren gegen Pattern, wenn sie behindern statt zu helfen.
Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „ErfinderDesRades“ ()
-
Hallo Leute
@SKeks
Klar muss die View für sich entscheiden wie sie was rendert, aber ich hätte das trotzdem gerne zentral gesammelt wie zum Beispiel in Application.Ressources. Wenn ich über das VM sagen kann welches Control genutzt wird warum ein weiteres Lay einführen?
In meinem Beispiel habe ich ein weiteres Usercontrol dazwischen. Geht allerdings auch direkt wie duu willstin der Application.xaml. Probiers mal. Funzt. Dann hast du wieder alles auf einem Platz.
kannst du das mit den Messages näher ausführen? Anwendung und Nutzen? Ich kann leider aus deinem Code ndas nicht rauslesen.
Sicher, aber leider erst am Abend wenn ich wieder daheim bin.
Das Beispiel von mir war natürlich realitätsfern.
Wie? Völlig egal wenn es um die funktionsweise von etwas ganz anderen geht. Lass dich bitte nicht verwirren.
@ErfinderDesRades
Sry - den Edit nicht gesehen - da siehste mal wie lange ich für sone Antwort brauche
OK, war auch gemein von mir, dachte ich war schnell genug mit dem Edit.
Aber damit ist mir immer noch nicht gezeigt, was nun ein Problem damit ist, und welche Lösung besser ist. Deine Lösung findich nicht besser, weil ist vielfach komplizierter und äusserst undurchschaubar.
Es geht NICHT darum welche Lösung besser ist, es geht darum welche korrekt ist. DU meinst immer alle ausbessern zu müssen, nicht ich. MVVM impliziert die strikte Trennung der Layer.
Wenn ich im Team Arbeite kann der "Designer" ungehindert Controls und Windows austauschen/umbenennen/abändern. Wenn das VM die V kennt kompiliert es nicht mehr, wo sich der Designer dann im Code nicht mehr auskennt und nicht weiter kann. Weiters, kann das selbe ViewModel für z.b. eine Windows 10 App oder eine HandyApp oder gut gemacht eine MVC Website verwendet werden.
Du trennst ja auch Model vom ViewModel damit man die Datenzugriffsschicht austauschen kann. Was wenn ich später mal von EntityFramework auf reinen SQL umsteigen will. Oder auf NHibernate.
Außerdem ist der Designer viel flexibler und muss nicht auf irgendwas aufpassen. Stickwort umbenennen.
Wenn der Kunde ins Lastenheft schreibt, er hätte doch gerne mal später vielleicht eine App welche die selben oder einen Teil der Funktionalitäten hat musst du dich mit deinem Ansatz wieder neu hinsetzen und das ganze VM wieder neu runtertippen. Genau deshalb. Das "Problem" wie du sagst, ist nicht wie du es machst. Ist ja auch gut und sicher einfacher. Aber es ist nicht MVVM, FAKT!!!!!
Dein RelayCommand geht so nicht:
Lerne gerne was neues wie schon mehrmals geschrieben. Hast du eine bessere Lösung. Die funzt bei mir so tadellos.
Und meine Lösung, um dass selbe VM mit verschiedenen Views anzuzeigen ist bodenlos trivial und verstößt gegen MVVM.
Was für mich ja keine heilige Kuh ist - ich verstoße halt ganz unverfroren gegen Pattern, wenn sie behindern statt zu helfen.
Moment, Moment. eines will ich klar stellen. Es wäre NIE zu dieser Diskussion gekommen wenn du nicht immer der jenige wärst der alle gern in die Schranken weist und meinst das dein Code der einzige wäre.
Ja, ich habe einige Posts von dir gelesen und das kommt tatsächlich so rüber. Du meinst selbst das du "unverfroren" gegen das Pattern verstößt weil es behindert. (Whaaaat?)
Oft behindert einem etwas, da geht man dem nicht aus dem Weg sondern stellt sich dem. War da nicht mal deine Devise?
OK, Idee. Wir nennen dein Pattern nun MVM und belassen es dabei das es auch MVVM noch gebe.
Hoffe das wir jetzt nicht dauernd zusammenstoßen, hab ich keinen bock drauf. Ich respektiere dich und weis das du was auf dem Kasten hast, auch respektiere ich deine Leistung hier im Forum.
15 Beiträge am Tag im Durchschnitt. wow. Ich habe leider einen Arbeitgeber auch.
Grüße
SaschaIf _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. ##
-
Tags
-
Ähnliche Themen
-
3 Benutzer haben hier geschrieben
- Nofear23m (22)
- SKeks (16)
- ErfinderDesRades (10)