Die Community zu .NET und Classic VB.
Menü

Tipp-Upload: VB.NET 0430: INotifyPropertyChanged-Basisklasse für MVVM (WPF)

 von 

Über den Tipp  

Dieser Tippvorschlag wird übernommen.

Der Vorschlag ist in den folgenden Kategorien zu finden:

  • Sonstiges

Dem Tippvorschlag wurden folgende Schlüsselwörter zugeordnet:
MVVM, WPF, VB.NET

Der Vorschlag wurde erstellt am: 24.02.2012 00:16.
Die letzte Aktualisierung erfolgte am 26.09.2017 20:11.

Zurück zur Übersicht

Beschreibung  

Wer mit dem M-V-VM Pattern in WPF arbeitet wird sicherlich das Problem kennen, dass man bei INotifyPropertyChanges den Propertynamen stets im Klartext angeben muss, was - bei Unachtsamkeit - zu Debugging-Orgien führen kann. Mit diesem Tipp möchte ich eine kleine Lösung zeigen, wie man sowas mit LINQ elegant umgehen kann und stets Typsicher bleibt, ohne gleich ein M-V-VM Framework verwenden zu müssen.
Im Beispiel zeige ich die Verwendung meiner Basisklasse nur im ViewModel, aber in den Models und BusinessModels lässt sich das natürlich genau so anwenden. Die Beispielanwendung merkt sich einfach mal die Fenstergröße und Position im MVVM-Pattern unter Verwendung dieser Basisklasse, ohne je eine Property namentlich benennen zu müssen. Zudem zeige ich hier, wie man die GetName() Methode verwendet, um ebenso typsicher auf Events reagieren kann, ohne Strings.
Die Anwendung ist recht einfach, jedes ViewModel, Model oder BusinessModel erbt von der Basisklasse:
Inherits ViewModelsBase

Anschließend lässt sich in jeder Property im Setter dies String-los ausführen:
OnPropertyChanged(Function() <NAME>, value)
Value wird hier für das Trace oder Debug-Logging gleich mit übergeben.
Und die GetName() Methode ermöglicht auch bei EventHandlern eine String-lose Behandlung, hier ein Beispiel:

Private Sub OnSizeChanged(sender As Object, e As PropertyChangedEventArgs) Handles Me.PropertyChanged
If e.PropertyName = GetName(Function() Width) Or e.PropertyName = GetName(Function() Height) Then
My.Settings.MainWindowSize = New System.Drawing.Size(_Width, _Height)
End If
End Sub

Schwierigkeitsgrad

Schwierigkeitsgrad 2

Verwendete API-Aufrufe:

Download:

Download des Beispielprojektes [13,71 KB]

' Dieser Source stammt von http://www.activevb.de
' und kann frei verwendet werden. Für eventuelle Schäden
' wird nicht gehaftet.

' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
' Ansonsten viel Spaß und Erfolg mit diesem Source!
'
' Beachten Sie, das vom Designer generierter Code hier ausgeblendet wird.
' In den Zip-Dateien ist er jedoch zu finden.

' --------- Anfang Projektdatei MVVM_Demo_App.vbproj ---------
' -------------- Anfang Datei MyWpfExtension.vb --------------
#If _MyType <> "Empty" Then

Namespace My
    ''' <summary>
    ''' Modul zum Definieren der im My-Namespace für WPF verfügbaren Eigenschaften
    ''' </summary>
    ''' <remarks></remarks>
    <Global.Microsoft.VisualBasic.HideModuleName()> Module MyWpfExtension

        Private s_Computer As New ThreadSafeObjectProvider(Of _
            Global.Microsoft.VisualBasic.Devices.Computer)

        Private s_User As New ThreadSafeObjectProvider(Of _
            Global.Microsoft.VisualBasic.ApplicationServices.User)

        Private s_Windows As New ThreadSafeObjectProvider(Of MyWindows)
        Private s_Log As New ThreadSafeObjectProvider(Of Global.Microsoft.VisualBasic.Logging.Log)

        ''' <summary>
        ''' Gibt das Anwendungsobjekt für die ausgeführte Anwendung zurück.
        ''' </summary>
        <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( _
            "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")>  Friend ReadOnly _
            Property Application() As Application

            Get
                Return CType(Global.System.Windows.Application.Current, Application)

            End Get

        End Property

        ''' <summary>
        ''' Gibt Informationen über den Hostcomputer zurück.
        ''' </summary>
        <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( _
            "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")>  Friend ReadOnly _
            Property Computer() As Global.Microsoft.VisualBasic.Devices.Computer

            Get
                Return s_Computer.GetInstance()

            End Get

        End Property

        ''' <summary>
        ''' Gibt Informationen über den aktuellen Benutzer zurück. Wenn Sie die Anwendung mit den aktuellen Windows-
        ''' Anmeldeinformationen ausführen möchten, rufen Sie My.User.InitializeWithWindowsUser() auf.
        ''' </summary>
        <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( _
            "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")>  Friend ReadOnly _
            Property User() As Global.Microsoft.VisualBasic.ApplicationServices.User

            Get
                Return s_User.GetInstance()

            End Get

        End Property

        ''' <summary>
        ''' Gibt das Anwendungsprotokoll zurück. Die Listener können in der Konfigurationsdatei der Anwendung konfiguriert werden.
        ''' </summary>
        <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( _
            "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")>  Friend ReadOnly _
            Property Log() As Global.Microsoft.VisualBasic.Logging.Log

            Get
                Return s_Log.GetInstance()

            End Get

        End Property

        ''' <summary>
        ''' Gibt die im Projekt definierte Windows-Auflistung zurück.
        ''' </summary>
        <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( _
            "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")>  Friend ReadOnly _
            Property Windows() As MyWindows

            <Global.System.Diagnostics.DebuggerHidden()> Get
                Return s_Windows.GetInstance()

            End Get

        End Property

        <Global.System.ComponentModel.EditorBrowsableAttribute( _
            Global.System.ComponentModel.EditorBrowsableState.Never)> _
            <Global.Microsoft.VisualBasic.MyGroupCollection( "System.Windows.Window", _
            "Create__Instance__", "Dispose__Instance__", _
            "My.MyWpfExtenstionModule.Windows")> Friend NotInheritable Class MyWindows

            <Global.System.Diagnostics.DebuggerHidden()> Private Shared Function _
                Create__Instance__(Of T As {New, Global.System.Windows.Window})(ByVal _
                Instance As T) As T

                If Instance Is Nothing Then
                    If s_WindowBeingCreated IsNot Nothing Then
                        If s_WindowBeingCreated.ContainsKey(GetType(T)) = True Then

                            Throw New Global.System.InvalidOperationException("The window " & _
                                "cannot be accessed via My.Windows from the Window " & _
                                "constructor.")

                        End If

                    Else

                        s_WindowBeingCreated = New Global.System.Collections.Hashtable()
                    End If

                    s_WindowBeingCreated.Add(GetType(T), Nothing)
                    Return New T()
                    s_WindowBeingCreated.Remove(GetType(T))

                Else

                    Return Instance
                End If

            End Function

            <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( _
                "Microsoft.Performance", "CA1822:MarkMembersAsStatic")>  _
                <Global.System.Diagnostics.DebuggerHidden()> Private Sub Dispose__Instance__( _
                Of T As Global.System.Windows.Window)(ByRef instance As T)

                instance = Nothing

            End Sub

            <Global.System.Diagnostics.DebuggerHidden()> _
                <Global.System.ComponentModel.EditorBrowsableAttribute( _
                Global.System.ComponentModel.EditorBrowsableState.Never)> Public Sub New()

                MyBase.New()

            End Sub

            <Global.System.ThreadStatic()> Private Shared s_WindowBeingCreated As _
                Global.System.Collections.Hashtable

            <Global.System.ComponentModel.EditorBrowsable( _
                Global.System.ComponentModel.EditorBrowsableState.Never)> Public Overrides _
                Function Equals(ByVal o As Object) As Boolean

                Return MyBase.Equals(o)

            End Function

            <Global.System.ComponentModel.EditorBrowsable( _
                Global.System.ComponentModel.EditorBrowsableState.Never)> Public Overrides _
                Function GetHashCode() As Integer

                Return MyBase.GetHashCode

            End Function

            <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( _
                "Microsoft.Performance", "CA1822:MarkMembersAsStatic")>  _
                <Global.System.ComponentModel.EditorBrowsable( _
                Global.System.ComponentModel.EditorBrowsableState.Never)> Friend Overloads _
                Function [GetType]() As Global.System.Type

                Return GetType(MyWindows)

            End Function

            <Global.System.ComponentModel.EditorBrowsable( _
                Global.System.ComponentModel.EditorBrowsableState.Never)> Public Overrides _
                Function ToString() As String

                Return MyBase.ToString

            End Function

        End Class
    End Module
End Namespace

Partial Class Application

    Inherits Global.System.Windows.Application

    <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( _
        "Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")> _
        <Global.System.Diagnostics.CodeAnalysis.SuppressMessageAttribute( _
        "Microsoft.Performance", "CA1822:MarkMembersAsStatic")> Friend ReadOnly Property _
        Info() As Global.Microsoft.VisualBasic.ApplicationServices.AssemblyInfo

        <Global.System.Diagnostics.DebuggerHidden()> Get

            Return New Global.Microsoft.VisualBasic.ApplicationServices.AssemblyInfo( _
                Global.System.Reflection.Assembly.GetExecutingAssembly())

        End Get

    End Property

End Class

#End If

' --------------- Ende Datei MyWpfExtension.vb ---------------
' ---------- Ende Projektdatei MVVM_Demo_App.vbproj ----------

	

Diskussion  

Diese Funktion ermöglicht es, Fragen, die die Veröffentlichung des Tipps betreffen, zu klären, oder Anregungen und Verbesserungsvorschläge einzubringen. Nach der Veröffentlichung des Tipps werden diese Beiträge nicht weiter verlinkt. Allgemeine Fragen zum Inhalt sollten daher hier nicht geklärt werden.

Um eine Diskussion eröffnen zu können, müssen sie angemeldet sein.