Die Community zu .NET und Classic VB.
Menü

Tipp-Upload: VB.NET 0369: PropertyNotifying

 von 

Über den Tipp  

Dieser Tippvorschlag ist noch unbewertet.

Der Vorschlag ist in den folgenden Kategorien zu finden:

  • Sonstiges
  • Steuerelemente

Dem Tippvorschlag wurden folgende Schlüsselwörter zugeordnet:
synchronisierung,propertydescriptor,reflection,databinding

Der Vorschlag wurde erstellt am: 14.05.2009 02:48.
Die letzte Aktualisierung erfolgte am 14.05.2009 02:48.

Zurück zur Übersicht

Beschreibung  

 VB.NET Tipp 90 synchronisiert verschiedene Steuerelemente miteinander, indem es Databinding zu einem gemeinsamen DatenObjekt herstellt.
PropertyNotifying kann Steuerelemente sowohl direkt miteinander verbinden, als auch mit DatenObjekten, als auch DatenObjekte untereinander.
Dabei wird unterschieden zw. einseitiger Benachrichtigung und gegenseitiger Synchronisierung.
Zusätzlich können Konverter zwischengeschaltet werden.
Als Notify-Sender geeignet sind Objekte, die eine der beiden folgenden Bedingungen erfüllen:
- INotifyPropertyChanged implementieren und das PropertyChanged-Event dieser Schnittstelle auslösen, oder
- der Property ein spezifisches Changed-Event zur Seite stellen (Property 'Text' -> Event 'TextChanged')
Das Interface folgt dem Flow-Interface-Pattern. Dadurch wird einerseits die Intellisense auf wenige, signifikante Optionen eingeschränkt (was die Bedienung erleichtert), andererseits der Code sehr kompakt und gut verständlich.

Schwierigkeitsgrad

Schwierigkeitsgrad 3

Verwendete API-Aufrufe:

Download:

Download des Beispielprojektes [14,84 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 Projektgruppe PropertyNotifyingUp.sln -------
' ------ Anfang Projektdatei PropertyNotifyingUp.vbproj ------
' ----------------- Anfang Datei frmMain.vb  -----------------
Public Class frmMain

    Public Sub New()

        InitializeComponent()

        ' ck1.Checked "benachrichtigt" HScrollBar1.Enabled und Textbox1.Text
        ' und synchronisiert sich mit ck2.Checked, bei invertierendem Konverter
        ck1.Property("Checked").Notify(HScrollBar1, "Enabled").Notify(TextBox1, "Text") _
            .Synchronisize(ck2, "Checked", Function(b As Boolean) Not b)

        ' HScrollBar1.Value benachrichtigt Me.Brightness und synchronisiert sich mit TextBox2.Text
        HScrollBar1.Property("Value").Notify(Me, "Brightness").Synchronisize(TextBox2, "Text")

    End Sub

    Public Property Brightness() As Byte
        Get
            Return MyBase.BackColor.A

        End Get

        Set(ByVal Value As Byte)

            ' drei gleiche Farbkomponenten ergeben einen Grauwert in angegebener Helligkeit
            MyBase.BackColor = Color.FromArgb(Value, Value, Value)

        End Set

    End Property

End Class

' ------------------ Ende Datei frmMain.vb  ------------------
' ------------- Anfang Datei PropertyNotifyX.vb  -------------
Imports System.Runtime.CompilerServices
Imports System.ComponentModel

Public Interface IPropertyNotify

    Function Notify(Of T As Class, TIn, TOut)( _
           ByVal other As T, ByVal prop As String, ByVal converter As Converter(Of TIn, TOut)) _
           As IPropertyNotify

    Function Notify(Of T As Class)(ByVal other As T, ByVal prop As String) As IPropertyNotify

    Function Synchronisize(Of T As Class, TIn, TOut)(ByVal other As T, ByVal prop As String, _
        ByVal converter As Converter(Of TIn, TOut), Optional ByVal backConverter As _
        Converter(Of TOut, TIn) = Nothing) As IPropertyNotify

    Function Synchronisize(Of T As Class)(ByVal other As T, ByVal prop As String) As IPropertyNotify

End Interface

Public Module PropertyNotifyX

    Private Class PropertyNotify(Of T As Class)

        Implements IPropertyNotify

        Private _item As Object, _prop As PropertyDescriptor

        Public Sub New(ByVal subj As T, ByVal subjProperty As String)

            _item = subj
            _prop = TypeDescriptor.GetProperties(subj)(subjProperty)

        End Sub

        Public Function Notify(Of T2 As Class)(ByVal other As T2, ByVal prop As String) _
                  As IPropertyNotify Implements IPropertyNotify.Notify

            Return Notify1(Of T2, Object, Object)(other, prop, Nothing)

        End Function

        Public Function Notify1(Of T1 As Class, TIn, TOut)( _
                  ByVal other As T1, ByVal prop As String, _
                  ByVal converter As Converter(Of TIn, TOut)) _
                  As IPropertyNotify Implements IPropertyNotify.Notify

            Dim otherProp = TypeDescriptor.GetProperties(other)(prop)

            Return SetListener(_item, _prop, other, otherProp, converter)

        End Function

        Public Function Synchronisize(Of T1 As Class)(ByVal other As T1, ByVal prop As _
            String) As IPropertyNotify Implements IPropertyNotify.Synchronisize

            Return Synchronisize1(Of T1, Object, Object)(other, prop, Nothing)

        End Function

        Public Function Synchronisize1(Of T1 As Class, TIn, TOut)(ByVal other As T1, ByVal _
            prop As String, ByVal converter As Converter(Of TIn, TOut), Optional ByVal _
            backConverter As Converter(Of TOut, TIn) = Nothing) As IPropertyNotify Implements _
            IPropertyNotify.Synchronisize

            Dim otherProp = TypeDescriptor.GetProperties(other)(prop)

            SetListener(_item, _prop, other, otherProp, converter)

            If backConverter Is Nothing Then Return SetListener(other, otherProp, _item, _
                _prop, converter)

            Return SetListener(other, otherProp, _item, _prop, backConverter)

        End Function

        Private Function SetListener(Of TIn, TOut)( _
                  ByVal src As Object, ByVal prpSrc As PropertyDescriptor, _
                  ByVal listener As Object, ByVal prpDest As PropertyDescriptor, _
                  ByVal converter As Converter(Of TIn, TOut)) As IPropertyNotify

            If Not prpSrc.SupportsChangeEvents Then

                Throw New ArgumentException(String.Concat(src.GetType.Name, " " & _
                    "implementiert nicht INotifyPropertyChanged, und die Eigenschaft ", _
                    ".", prpSrc.Name, " ist auch nicht mit einem Changed-Event " & _
                    "assoziiert"))

            End If

            Dim ValueChangedHandler As EventHandler = Function(sender, e) PropHelper(Of TIn, _
                TOut)(sender, prpSrc, listener, prpDest, converter)

                prpSrc.AddValueChanged(src, ValueChangedHandler)
                ValueChangedHandler(src, EventArgs.Empty) ' erstmalige Synchronisation durchführen
                Return Me

            End Function

            Private Shared Function PropHelper(Of TIn, TOut)(ByVal src As Object, ByVal _
                prpSrc As PropertyDescriptor, ByVal dst As Object, ByVal prpDest As _
                PropertyDescriptor, ByVal converter As Converter(Of TIn, TOut)) As Object

                Dim newVal = prpSrc.GetValue(src)

                If converter IsNot Nothing Then
                    newVal = converter(DirectCast(newVal, TIn))

                ElseIf prpSrc.PropertyType.Equals(prpDest.PropertyType) Then

                    ' nixtun
                ElseIf prpDest.Converter.CanConvertFrom(prpSrc.PropertyType) Then

                    newVal = prpDest.Converter.ConvertFrom(newVal)

                ElseIf prpSrc.Converter.CanConvertTo(prpDest.PropertyType) Then

                    newVal = prpSrc.Converter.ConvertTo(newVal, prpDest.PropertyType)
                End If

                If Object.Equals(newVal, prpDest.GetValue(dst)) Then Return Nothing
                prpDest.SetValue(dst, newVal)
                Return Nothing

            End Function

        End Class

        ' Diese Extension ist quasi der "Einstieg" in das IPropertyNotify-Flow-Interface
        <Extension()> Public Function [Property](Of T As Class)(ByVal subj As T, ByVal Name _
            As String) As IPropertyNotify

            Return New PropertyNotify(Of T)(subj, Name)

        End Function

    End Module

    ' -------------- Ende Datei PropertyNotifyX.vb  --------------
    ' ------- Ende Projektdatei PropertyNotifyingUp.vbproj -------
    ' -------- Ende Projektgruppe PropertyNotifyingUp.sln --------

	

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.