| |
VB.NET - Ein- und UmsteigerKlasse erstellen, mit Eigenschaft die gebunden werden kann | | | Autor: Manni01 | Datum: 15.11.12 18:12 |
| Hallo,
ich möchte eine einfache Klasse erstellen, die eine Eigenschaft "Wert" vom Typ Object besitzt. Zur Laufzeit kann diese Eigenschaft verschiedene Datentypen annehmen (z.B. Bool, Integer, Singel, String).
Diese Eigenschaft "Wert" möchte ich später an verschiedene Steuerelemente per Databinding binden. Meine Frage ist: Was muss ich dabei beachten? Einige Versuche sowie entsprechende Suche im Netz hat mich bisher leider nicht weitergebracht.
Dabke für Eure Hinweise... | |
Re: Klasse erstellen, mit Eigenschaft die gebunden werden kann | | | Autor: Manfred X | Datum: 15.11.12 19:55 |
| Ergänzender Hinweis:
Du könntest bei dem jeweils zugewiesenen Datentyp
überprüfen, ob er einem der erwarteten Typen entspricht.
Public Class aClass
Private _anObject As Object
Public Property AnObject As Object
Set(value As Object)
If Not IsTypeAllowed(value) Then
Throw New ArgumentException("Illegal Datatype")
End If
_anObject = value
End Set
Get
Return _anObject
End Get
End Property
Private Function IsTypeAllwed(ByVal value As Object) As Boolean
Dim ty As Type = value.GetType
If Not ty.IsPrimitive And _
Not ty.Equals(GetType(Decimal)) And
Not ty.Equals(GetType(String)) Then
Return False
End If
Return True
End Function
End Class | |
Re: Klasse erstellen, mit Eigenschaft die gebunden werden kann | | | Autor: Manni01 | Datum: 16.11.12 06:36 |
| Danke für die schnelle Antwort. Ich dachte auch, dass das einfach ist, irgendwas mache ich trotzdem falsch. Bei der Bindung wird der richtige Wert angezeigt. Bei Änderung wird der Wert nicht aktualisiert. So habe ich es gemacht:
Public Class Item
Public Name As String
Private _Wert As Object = 0
Public Property Wert As Object
Get
Return _Wert
End Get
Set(ByVal value As Object)
_Wert = value
End Set
End Property
End Class Und dann in der Form das Binding an Label1:
Label1.DataBindings.Add(New Binding("Text", Automatik, "Wert")) Zusatzinfo: von der Bindingklasse wird Anfangs nur einmal das Format-Ereignis geworfen. Danach passiert nichts mehr wenn sich der Wert ändert.
Beitrag wurde zuletzt am 16.11.12 um 06:55:00 editiert. | |
Noch eine Info... | | | Autor: Manni01 | Datum: 16.11.12 07:16 |
| Wenn ich Binding.ReadValue aufrufe wird der Wert aktualisiert. Nur automatisch geht es halt nicht. | |
Re: Noch eine Info... | | | Autor: FZelle (Moderator) | Datum: 16.11.12 10:30 |
| Wenn Du das Bining so erstellst, wird der wert erst eingetragen wenn das Control den Fokus verliert.
Du solltest evtl mal die weiteren Überladungen von Add() anschauen. | |
Re: Danke, Problem gelöst, nur noch ein Frage dazu... | | | Autor: Manni01 | Datum: 16.11.12 10:54 |
| Danke Euch allen, das war der entscheidende Hinweis, der Datenbindungsmechanismus hängt sich also an das Ereignis. Auch die Überladungen von Add hatte ich mir schon angesehen und werde sie entsprechend verwenden, da Änderungen auch bidirektional erfolgen müssen.
Jetzt kommt die Kür: Die Eigenschaft "Wert" kann auch von einem anderen Thread (in diesem Fall ein Backgroundworker) geändert werden. Dann habe ich natürlich einen "unzulässigen threadübergreifenden Vorgang". Gibt es eine einfache Möglichkeit das Ereignis für's Databinding immer auf den richtigen Thread zu heben?
Die Klasse sieht jetzt so aus:
Public Class Item
Implements INotifyPropertyChanged
Public Name As String
Private _Wert As Object = 0
Public Event PropertyChanged(sender As Object, e As _
PropertyChangedEventArgs) Implements _
INotifyPropertyChanged.PropertyChanged
Public Property Wert As Object
Get
Return _Wert
End Get
Set(value As Object)
If value <> _Wert Then
_Wert = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs( _
"Wert"))
End If
End Set
End Property
End Class Danke nochmal...
Beitrag wurde zuletzt am 16.11.12 um 11:13:28 editiert. | |
Re: Danke, Problem gelöst, nur noch ein Frage dazu... | | | Autor: Manni01 | Datum: 16.11.12 12:25 |
| Danke für die Hinweise. Ich habe mich nicht korrekt genug ausgedrückt. Die Wertänderung muss nicht immer von einem BGW kommen. Da diese Klasse in einer separaten DLL sitzt, weiß ich nicht genau ob der Anwender der Klasse die Wertänderung von einem anderen Thread aus macht, als der mit dem die Klasse erzeugt wurde.
Meines Wissens wäre der "normale" Weg bei Wertänderung auf dem Formthread mit InvokeRequired und Invoke über einen Delegaten die entsprechende Methode aufzurufen und der Anwender müsste irgendwie in den Databinding-Prozess eingreifen. Das alles möchte ich dem Anwender ersparen.
Ich müsste in meiner Klasse "Item" das Ereignis "PropertyChanged" immer auf dem Thread werfen, der die Klasse auch erzeugt hat. Wie ich das hinbekomme weiss ich nicht. | |
Re: Danke, Problem gelöst, nur noch ein Frage dazu... | | | Autor: Manfred X | Datum: 16.11.12 12:38 |
| Wie jemand deine Klasse im Rahmen von Binding und Threading einsetzt,
ist dessen Problem.
Deine Klasse übernimmt Eigenschaften, führt ggf. ihre
Methoden durch und löst dabei ihre Events aus. Sonst kann die nix machen.
Du könntest eventuell ein Usercontrol erstellen, das Daten intern verwaltet
und dann viele Aufgaben dort hin verlagern. Oder ein komplettes Formular
mit allen erforderlichen Funktionen ausstatten.
Der Anwendungsprogrammierer muss übrigens nur richtig Invoken, das Databinding
klappt dann schon.
Beitrag wurde zuletzt am 16.11.12 um 12:41:49 editiert. | |
Re: Danke, Problem gelöst, nur noch ein Frage dazu... | | | Autor: Manni01 | Datum: 16.11.12 12:51 |
| Grundsätzlich gebe ich Dir Recht. Aber es wäre doch eine tolle Sache, wenn der Anwender sich 1. keine Gedanken um dieses Dinge machen muss und 2. auch noch einen Haufen sich immer wiederholender Arbeit spart.
Gibt es eine Möglichkeit festzustellen auf welchem Thread die Klasse erzeugt wurde und ob eine Wertänderung von einem anderen Thread erfolgt? Wenn man dies feststellen kann, müsste man das Ereignis "PropertyChanged" nur noch auf dem richtigen Thread werfen und alles wäre gut. | |
Re: Danke, Problem gelöst, nur noch ein Frage dazu... | | | Autor: Manfred X | Datum: 16.11.12 13:04 |
| Und warum erstellst Du kein Basis-Formular, das bereits die erforderlichen Controls
besitzt und eine zugehörige Datenklasse (incl. DataBindings) verwaltet.
Von dieser Klasse kann der Anwendungsprogrammierer seine eigenen Formulare ggf. ableiten. | |
Re: Danke, Problem gelöst, nur noch ein Frage dazu... | | | Autor: Manni01 | Datum: 16.11.12 13:22 |
| Wäre auch eine Möglichkeit, aber soweit wollte ich nicht gehen, da ich nicht weiss wie die Klassen später angewendet werden (evtl. gibt es gar keine Form). Die Klasse wäre dann nicht mehr so universell einsatzbar. | |
Re: Danke, Problem gelöst, nur noch ein Frage dazu... | | | Autor: Manfred X | Datum: 16.11.12 13:47 |
| Der Anwender kann doch selbst entscheiden,
- ob er das Formular einsetzen will, das die Oberfläche für
die Datenklasse managed und eine Instanz kapselt oder
- ob er keine Oberfläche benötigt und deshalb die Daten-Klasse
selbst direkt instanziiert (Databinding entfällt in dem fall ja ohnehin). | |
Re: Danke, Problem gelöst, nur noch ein Frage dazu... | | | Autor: Manni01 | Datum: 16.11.12 15:02 |
| Das ist richtig, es ist aber auch alles eine Frage des Aufwands. Wenn es nun eine einfache Möglichkeit für meine "Item"-Klasse wie oben beschrieben gegeben hätte, wäre es ok. Es kann z.B. durchaus vorkommen, dass mehrere 1000 Items verwendet werden. Es soll alles klein und schlank bleiben, vom Termindruck einmal ganz abgesehen.
Wenn es wirklich keine relativ einfache Möglichkeit gibt einerhalb dieser Klasse das CrossThreading zu vermeiden, dann ist das halt leider so und der Anwender muss das Problem lösen. Evtl. kann ich mich zu einem späteren Zeitpunkt nochmal darum kümmern. | |
Re: Danke, Problem gelöst, nur noch ein Frage dazu... | | | Autor: Manfred X | Datum: 16.11.12 15:17 |
| Mehrere tausend Items? Na und?
Verwende z.B. eine Bindinglist (System.ComponentModel)
für die Aufbewahrung. Und erstelle z.B. ein UserControl für
die Verwaltung der Eigenschaften einer Instanz Deiner
Datenklasse. | |
Re: Danke, Problem gelöst, nur noch ein Frage dazu... | | | Autor: keco | Datum: 16.11.12 16:57 |
| Wenn es unbedingt auf diesem ungewöhnlichen Weg funktionieren soll, dann könntest du einen SynchronisationContext verwenden. Deine Klasse kann eine Eigenschaft anbieten, damit der Anwender den Context für den UI-Thread angeben kann. Deine Events löst du dann über diesen Context aus. Damit wird die Ausführung aller an die Ereignisse angehangenen Methoden im Kontext des UI-Threads ausgeführt.
Für gewöhnlich hat aber der Benutzer selbst dafür Sorge zu tragen. | |
Re: Klasse erstellen, mit Eigenschaft die gebunden werden kann | | | Autor: Manni01 | Datum: 19.11.12 08:26 |
| Da ich historisch bedingt eher von der hardwarenahen, echtzeitfähigen Programmierung komme, habe ich ständig die Ressourcen, die ein Programm benötigt, im Blick. Davon muss ich mich wohl langsam ein wenig lösen.
Danke nochmal an alle für die Ideen und Anregungen. | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
Neu! sevCommand 4.0
Professionelle Schaltflächen im modernen Design!
Mit nur wenigen Mausklicks statten auch Sie Ihre Anwendungen ab sofort mit grafischen Schaltflächen im modernen Look & Feel aus (WinXP, Office, Vista oder auch Windows 8), inkl. große Symbolbibliothek. Weitere InfosTipp des Monats Access-Tools Vol.1
Über 400 MByte Inhalt
Mehr als 250 Access-Beispiele, 25 Add-Ins und ActiveX-Komponenten, 16 VB-Projekt inkl. Source, mehr als 320 Tipps & Tricks für Access und VB
Nur 24,95 EURWeitere Infos
|