Tipp-Upload: VB.NET 0369: PropertyNotifying
von Spatzenkanonier
Ü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.
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 |
Verwendete API-Aufrufe: |
Download: |
' 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.