...

End Class - Microsoft

by user

on
Category: Documents
15

views

Report

Comments

Transcript

End Class - Microsoft
Da VB a VB.NET
Andrea Saltarello [IDevGuro]
Corrado Cavalli [DevGuro(Of T)]
Sponsor
Golden migration rule...
.Non migrare!
VB.NET è un nuovo linguaggio
Il wizard fa del suo meglio ma non fa i miracoli
Scelta di un Project Template
Windows Application
Class Library
Windows Control Library
ASP .NET Web Application / Service /
Control Library
Console Application
Windows Service
Smart Device App
Office App (VSTO)
Overview del .NET Framework
C++
C#
J#
Common Language Specification
.NET Framework
…
Visual Studio .NET
Visual
Basic
Struttura di un Progetto
Solution Files (.sln, .suo)
Project Files (.vbproj)
Local Project Items
Classi, Form, Moduli, ecc. (.vb)
Web Project Items
XML Web services (.asmx)
Web Form (.aspx)
Global application classes (.asax)
Parte #1
Il linguaggio Visual Basic .NET
Definire classi
In VB6, una classe:
è un file .cls
Ha come nome il nome del file (es:
Customer.cls)
In VB.NET, una classe:
È un blocco di codice Class…End Class
In un unico file ci possono essere più classi
VB.NET=OOP!
<Scope> Class Car
…
End Class
File Class1.vb
Public Class Car
Public Sub Start()
End Sub
End Class
VB 2005
Dim T As New Car()
T.Start()
T.Stop()
VB 2005
File Class2.vb
Public Partial Class Car
Public Sub Stop()
End Sub
End Class
VB 2005
Uso dei Costruttori
Sub New rimpiazza Class_Initialize
Viene eseguita quando l’oggetto è istanziato
Public Sub New( )
intValue = 1
End Sub
Possiamo specificare più costruttori
per la stessa classe (Overload)
Public Sub New(ByVal i As Integer)
intValue = i
End Sub
Distruzione degli oggetti
Sub Finalize rimpiazza l’evento Class_Terminate
La usiamo per liberare le risorse usate dall’oggetto
Viene eseguita quando il GC distrugge l’oggetto
Usiamo x = Nothing per permettere la Garbage Collection
Attenzione: la distruzione potrebbe non avvenire
immediatamente!
Protected Overrides Sub Finalize( )
‘Rilascio delle risorse
End Sub
Dichiarazione di Funzioni
Stessa Sintassi di Visual Basic 6.0
Una classe può contenere metodi con stesso
nome e signature differente
una alternativa ai parametri Optional
più robusti: errori a compile time
Non deve esistere ambiguità
I metodi non possono differire solo per il tipo di
ritorno o argomenti opzionali
Public Function ToInt(ByVal o as Object) As Integer
End Sub
Public Function ToInt(ByVal s as String) As Integer
End Sub
Dichiarazione di Proprietà
Sintassi differente da quella di Visual Basic 6.0
Public Property MyData( ) As Integer
Get
Return intMyData
'Restituisce una variabile locale
End Get
Set (ByVal Value As Integer)
intMyData = Value
‘Memorizza il valore in una variabile
End Set
End Property
Keyword ReadOnly e WriteOnly
Public ReadOnly Property MyProperty( ) As Integer
Get
Return _MyProperty
End Get
End Property
VB.NET=Ereditarietà
Classi con funzionalità e interfacce molto simili ad un altra
Modifica della classe (errori,interfaccia non congrua)
Copia e Incolla
Il codice potrebbe non essere disponibile
Eredità per delega (favour object composition over inheritance – cit.)
Parecchio codice per il wrapping della classe interna
SuperCar
Start
Start
Car
Faster
Ereditarietà
Creare una classe che eredita da un altra
Eredita Interfaccia e Implementazione
Inherits
Non è necessario
Source Code
Stesso linguaggio (C# <-> VB.NET)
Public Class SuperCar
Inherits Car
End Class
Dim sc as New SuperCar
sc.Start()
Sc.Faster()
Public Class SuperCar
Inherits Car
Public Sub Turbo
End Sub
End Class
Dim sc as New SuperCar
sc.Start()
‘Car
sc.Faster()
‘Car
sc.Turbo()
‘SuperCar
Ereditarietà
Concetti
La classe da cui si eredita è definita classe Base
Posso ereditare da qualsiasi classe .NET (che lo permette)
Tutte le classi in .NET ereditano da System.Object
Si definisce una relazione “Is a” (é un)
In .NET tutto è Object
Public Class SuperCar
Inherits Car
Public Sub Turbo
End Sub
End Class
Dim c as Car= New SuperCar
c.Start()
c.Turbo()
‘Errore
Una classe può ereditare da una sola classe base
Single Inheritance
Override
La classe che eredita può modificare il comportamento della
classe base
Ridefinendone i metodi/proprieta/eventi
La classe base deve permetterne la redifinizione
Overridable
Public Class Car
Public Overridable Sub Faster
Console.WriteLine(“base”)
End Sub
End Class
Public Class SuperCar
Inherits Car
Public Overrides Sub Faster
Console.WriteLine(“Inherited”)
End Sub
End Class
Dim c as New SuperCar
c.Faster()
‘Inherited
Override
Un metodo dichiarato Overrides:
E’ automaticamente Overridable
Si può usare NotOverridable per modificarne il comportamento
Public Class SuperCar: Inherits Car
Public NotOverridable Overrides Sub Faster
Console.WriteLine(“Inherited”)
End Sub
End Class
MyBase
Rappresenta la classe da cui si sta ereditando
Public Class SuperCar: Inherits Car
Public Overrides ReadOnly Property Model as String
Return MyBase.Model + “ Super”
End Sub
End Class
Override
I costruttori non vengono ereditati
No problem se non avete dei costruttori parametrici (usa default)
Dovete invocarli esplicitamente (prima istruzione)
Public Class Car
Public Sub New (cilindrata as Integer)
End Sub
End Class
Public Class SuperCar: Inherits Car
Public Sub New (cilindrata as Integer)
MyBase.New(cilindrata)
‘Inizializzo la classe base
End Sub
End Class
Override, classe base e Me
Quando associate un istanza di una classe ereditata ad una variabile di
tipo base, la classe base “vede” l’implementazione dei metodi della
classe ereditata
Public Class Car
Public Overridable Sub Faster
Console.WriteLine(“base”)
End Sub
End Class
Public Class SuperCar: Inherits Car
Public Overrides Sub Faster
Console.WriteLine(“Inherited”)
End Sub
End Class
Dim c as Car= New SuperCar
c.Faster()’
Inherited
Me non indica il contesto corrente
Public Class Car
Private Sub IncreaseSpeed
Me.Faster()
End Sub
End Class
MyClass
MyClass permette di specificare che il contesto di esecuzione sia quello
della classe base e non quello di eventuali overrides in classi ereditanti
da essa
Public Class Car
Private Sub IncreaseSpeed
MyClass.Faster()
End Sub
End Class
Viene eseguito il metodo Faster della classe Car
Non disponibile in C#
Shadows
Overrides funziona se il metodo della classe base è virtual
Potrebbe non esserlo (I metodi Overridable sono più ‘lenti’)
Potremmo non poterlo modificare
Shadows
Permette di ridefinire metodi già presenti nella classe base
Sono a tutti gli effetti delle nuove implementazioni
Sono ignorate dalla classe base (no ereditarietà)
Va usato per ridefinire membri Shared
Public Class SuperCar: Inherits Car
Public Shadows Sub Faster
Console.WriteLine(“Inherited”)
End Sub
End Class
Dim c as Car= New SuperCar
c.Faster()’
base
In alcuni casi potremmo non volere che qualcuno erediti la nostra
classe
NotInheritable e MustInherit
NotInheritable
Indica che la classe non è ereditabile (sealed class)
Public NotInheritable Class Car
End Class
Public Class SuperCar
Inherits Car ‘Errore
End Class
MustInherit
Non può essere istanziata (abstract class)
Può essere usata solo ereditando da essa
Spesso contiene dei metodi definiti MustOverride
Permette di definire delle classi che hanno funzionalità
parziale
Public MustInherit Class Car
Public MustOverride Sub Faster
End Sub
End Class
Classe Astratta: CollectionBase
System.Collection.CollectionBase
Permette di creare collezioni tipizzate
Public Class Cars : Inherits CollectionBase
Public Sub Add(ByVal item As Car)
MyBase.InnerList.Add(item)
End Sub
Default Property Item(ByVal index As Integer) As Car
Get
Return DirectCast(MyBase.InnerList(index), Car)
End Get
Set(ByVal Value As Car)
MyBase.InnerList(index) = Value
End Set
End Property
End Class
Dim l as New Cars()
l.Add(new Car)
l.Add (New Truck)
‘ok
‘Errore
VB 2005 - Generics
Permettono di definire dei tipi “generici” che verrano “completati” a
compile time
Public Class Car(Of
Car
T)
Private _Navigator As T
Placeholder
Public ReadOnly Property Navigator As T
Get
Return _Navigator
Public Class TomTom
End Get
Public Sub RouteTo():End Sub
End Class
End Class
Public Class Garmin
Public Sub NavigateTo():End Sub
End Class
Dim Car1 As New Car(Of TomTom)
Dim Car2 As New Car(Of Garmin)
Car1.Navigator.
VB 2005 – Generics Collections
Public
Class List
List(Of T)
Public Class
Private
Private elements()
elements() As
As T
Object
Private
Private count
count As
As Integer
Integer
Public
Public Sub
Sub Add(ByVal
Add(ByVal element
element As
As T)
Object)
If
count
=
elements.Length
Then
If count = elements.Length Then Resize(count
Resize(count *
* 2)
2)
elements(count)
=
element
:
count
+=
1
elements(count) = element : count += 1
End
End Sub
Sub
Public
Default
Property
Item(ByVal
_ _
Dim
intList
As New
List() Index
Public
Default
Property
Item(ByVal
Index
Dim intList
As Integer)
As Object
T As New List(Of Int32)
‘ Boxing!
Get intList.Add(1)
intList.Add(1)
No Boxing!
intList.Add(2)
‘ ‘Boxing!
Return
elements(index)
intList.Add(2)
‘No
Noerror…
Boxing!
intList.Add(“Pippo")
‘

End
Get
End Get
intList.Add(“Pippo")
‘ Error… 
Set
Set (value
(value as
as object)
T)
i = CInt(intList(0))
‘ Richiesto cast
elements(index)
= value
elements(index)
=
value
i = intList(0)
‘ Non serve castare
End Set
End
Set
End
Property
Property
EndEnd
Class
End Class
VB 2005 – Generics Methods
Public Function MyIIF (Of T)(cond As Boolean, _
trueP As T, falseP As T) As T
If (cond) Then
Return trueP
Else
Return falseP
End If
End Sub
Dim X As Int32 = 3
Dim Y As Int32 = 4
Dim Z As Int32 = IIf(X>Y,X,Y) ‘Error
Dim Z As Int32 = MyIIF(Of Int32)(X>Y,X,Y) ‘No cast!
Dim Z As Int32 = MyIIF(X>Y,X,Y) ‘ Type inferencing
VB 2005 – Generics Constraints
Public Class Car(Of T
T)As New)
Private _Navigator As New
T
T
Public ReadOnly Property Navigator As T
Get
Return _Navigator
End Get
End Class
Dim Car1 As New Car(Of TomTom)
Car1.Navigator.RouteTo()’ Error
Public Class Car _
(Of T As {New,BaseClass,I1,I2,Class,Structure})
Private _Navigator As New T
Public ReadOnly Property Navigator As T
Get
Return _Navigator
End Get
End Class
VB.NET: Approfondimenti
“Da VB a VB.NET”, Andrea Saltarello, workshop
14/11/2001
“Language Revolution”, Corrado Cavalli e
Raffaele Rialdi, “Whidbey workshop”
An Introduction to Visual Basic 2005, Jay Roxe
e Sean Draine, “Whidbey (Reloaded) workshop”
Classi Attributo
Le classi attributo:
dal punto di vista dell’utilizzatore, sono espressioni utili per decorare
porzioni di codice
Dal punto di vista del realizzatore, sono classi che specializzano
System.Attribute
E’ raccomandato l’uso del suffisso Attribute nella definizione del nome delle
suddette classi
Il suffisso può essere omesso in fase di decorazione del codice
Public Class ReportManager
<Obsolete(“Dovresti usare PrintLabel(Int32)”)> _
Public Sub PrintLabel()
PrintLabel(1)
End Sub
Public Sub PrintLabel(ByVal copies As Integer)
End Sub
End Class
Attributi: approfondimenti
“Componenti "Alternativi": le classi
Attributo”, Andrea Saltarello, workshop
“Component Development”
Parte #2
VB.NET vs. Windows Forms
Localizzazione in VB6
VB6
Aggiunta di un file .res al progetto
Utilizzo del resource editor
Localizzare testo usando
LoadResString
LoadResPicture
LoadResData
No local/region aware
Difficile integrare culture
diverse
Difficile estendere la
localizzazione
No locale adaptive UI
Localizzazione in .NET
VB.NET
Si appoggia su files xml (.resx)
ResGen.exe .resx -> .resources
ResourceManager
Cerca le assembly satellite utilizzando la cultura della UI
Probing
<language-culture>
<language>
Neutral / Default culture
Tools
WinRes.exe
Lutz Roeder’s Resourcer (http://www.aisto.com/roeder/dotnet/)
Al.exe
Localizzazione: Approfondimenti
“Applicazioni Windows Forms localizzate”,
Corrado Cavalli, articolo.
Applicazioni MDI
Proprietà IsMdiContainer = True per
“promuovere” un form allo stato di contenitore
MDI
Nessun limite sul numero di form MDI per applicazione
Proprietà MdiParent = mdiform per “incastrare” il
form MDI child
un form MDI può ospitare *qualsiasi* controllo
sulla sua superficie
Controlli Owner drawn
Alcuni controlli (es: Menu, ListBox e
ComboBox) espongono la proprietà
DrawMode, che può essere impostata a:
Normal
OwnerDrawFixed
OwnerDrawVariable
L'evento DrawItem riceve un riferimento
all’elemento (es: l’indice) e un oggetto
Graphics
Delegate
Le delegate sono dei puntatori a funzione:
Managed. Non abbiamo in mano un vero
puntatore a funzione, ma un oggetto in
grado di rintracciarlo. Il GC non ci
preoccupa: CLR e FX sono in combutta e
mantengono valido il “puntatore”
type-safe. Le funzioni devono rispettare la
firma della delegate
Multithreading
Il framework offre la classe Thread, che
accetta in ingresso una istanza della
delegate ThreadStart
Asyncronous Programming
Il cliente vuole applicazioni “veloci”
Ottimizzare la velocità apparente
Collo di bottiglia... Attendere prego... Applicazione Freezed
Application.DoEvents()
Eseguire l’operazione in un thread separato
Non è consentito accedere a controlli Windows da threads
diversi da quello in cui il controllo è stato creato
Gli unici metodi thread-safe di un controllo windows sono
Invoke
BeginInvoke
EndInvoke
CreateGraphics
ISyncronizeInvoke
InvokeRequired,Invoke,BeginInvoke,EndInvoke
Control implementa ISyncronizeInvoke
InvokeRequired
Ritorna True se il thread che invoca la proprietà è
diverso da quello che ha creato il controllo
Non siamo sicuri se è safe accedere al controllo
Metodi always safe
public readonly property InvokeRequired() as boolean
get
Dim procId as Integer
Dim WinThId = GetWindowThreadProcessId(Me.Handle, procId)
return AppDomain.GetCurrentThreadId()<>WinThId
end get
End property
Asyncronous Delegates
I delegates possono essere utilizzati per eseguire operazioni
asincrone
BeginInvoke
Ritorna IAsyncResult
IAsyncResult.IsCompleted
BeginInvoke (AsyncCallback,Object)
Invoca AsyncCallback al termine dell’operazione
AsyncCallback(ByVal ar as IAsyncResult)
Object viene passato alla procedura di callback
In AsyncCallback deve essere invocato EndInvoke
AsyncCallback viene invocata in un thread separato
Il thread proviene dal ThreadPool
BeginInvoke/EndInvoke posson generare delle eccezioni
Non è possibile interropere BeginInvoke
GUI Asincrona: Approfondimenti
“Accesso Thread-Safe a controlli
Windows Forms”, Corrado Cavalli,
articolo.
Parte #3
Accesso ai dati
Prerequisiti
v1.x: deploy manuale di MDAC 2.7+
v2.0: non necessitano di MDAC:
Classi base, comuni (System.Data.Common)
e disconnesse
.NET managed provider per SQL Server e
Oracle
v2.0: usano MDAC, senza
particolari requisiti:
Managed provider OLEDB e ODBC
Vanno bene le versioni 2.6, 2.7, 2.8 o… 9.0
Struttura di ADO .NET
ADO .NET è composto da:
Namespace System.Data: racchiude le primitive
indipendenti dalla tipologia di base dati.
Sono tutte disconnesse
.NET Managed Provider: implementano le primitive
necessarie all’accesso a specifiche basi dati
System.Data.SqlClient per l’accesso a SQL Server 7+
System.Data.OleDb per connettersi usando un OleDb
Provider
System.Data.OracleClient
System.Data.Odbc
Common Provider Model
ADO.NET v1.0/1.1 è basato su alcune
interfacce
•
E’ problematico scrivere codice indipendente dalla
base dati
ADO .NET 2.0 è basato su classi base
condivise dai provider
•
•
•
E’ una estensione, non introduce incompatibilità
La sintassi SQL è comunque specifica per la base
dati!
Architettura basata sul pattern Factory
.NET Data Providers
Implementano un insieme comune di
interfacce esponendo le classi:
Connection: permette la connessione ad una
base dati
Command: permette l’esecuzione di comandi
SQL e Stored Procedure
DataReader: implementa un cursore forwardonly, read-only, client side
DataAdapter: permette di “riempire” un
contenitore disconnesso
Classe Connection
Simile ad ADO old-style
La Connection String:
Può essere specificata mediante un costruttore
parametrico
Utilizza le stesse keyword di ADODB
Richiede attenzione nella specifica del Provider:
SqlClient non lo accetta
System.Data.OleDb non supporta ODBC
Dim conSQL As New SqlConnection( )
conSQL.ConnectionString = "Integrated Security=True;" & _
"Data Source=LocalHost;Initial Catalog=Pubs;"
conSQL.Open( )
Classe Command
Possiamo creare un comando:
Mediante il costruttore
Mediante metodo CreateCommand
Possiamo eseguire un comando mediante i metodi:
ExecuteReader: restituisce il DataReader in base ad una
query
ExecuteScalar: è il metodo preferibile se il risultato è un
singleton
ExecuteNonQuery: esegue un comando di azione
Dim commSQL As New SqlCommand( )
commSQL.Connection = conSQL
commSQL.CommandText = "Select Count(*) from Authors"
MessageBox.Show(commSQL.ExecuteScalar( ).ToString)
Invocare Stored Procedure
1.
2.
3.
4.
5.
6.
7.
8.
Creare un oggetto Command
Impostare CommandType al valore StoredProcedure
Impostare la proprietà CommandText
Usare il metodo Add per creare e aggiungere
parametri
Impostare la proprietà ParameterDirection
Invocare ExecuteReader
Consumare i record, e chiudere il DataReader
Leggere i parametri di output e il valore di ritorno
Usare un DataReader
Per usare un DataReader, possiamo:
Avanzare alla posizione successiva mediante il
metodo Read(), che ritorna True finchè non si sono
consumati tutti i dati
Leggere i valori dei campi mediante la proprietà Item,
oppure mediante i metodi GetXYZ()
Un DataReader impegna la propria connessione,
quindi:
Non è possibile utilizzarla per eseguire comandi
Dobbiamo ricordarci di chiuderlo mediante il metodo
Close()
M.A.R.S.
In v2.0, Multiple Active Results Sets:
Mantiene disponibile una connessione quando apriamo
un SqlDataReader al fine di poter:
Eseguire un’altra query per ottenere un DataReader/XmlReader
Eseguire comandi DML
permette differenti result set contemporaeamente attivi:
alternare fetch ad ogni reader
Alternare query che non restituiscono reader
Mediante MARS, è sufficiente una sola connessione se:
I dati risiedono nello stesso database
Usiamo SQL Server 2005/MDAC9
M.A.R.S.
Dim parentReader As DataReader = Command1.ExecuteReader()
While parentReader.Read()
' process parent row data here
' then get rowset from child table
Command2.Parameters("@id").Value = parentReader("id")
Dim childReader As DataReader = Command2.ExecuteReader()
' process child rows here
childReader.Close()
End While
parentReader.Close()
La classe DataTable
E’ il contenitore dati disconnessi di
ADO.NET
La classe DataTable espone le proprietà:
Columns: è una collezione di istanze di
DataColumn
Rows: è una collezione di istanze della
classe DataRow
Una istanza della classe DataRow:
Mette a disposizione il contenuto delle proprie
colonne mediante la proprietà Item
Popolare una DataTable
Popolare una DataTable accedendo ad un
RDBMS
Dim adaptSQL As New SqlClient.SqlDataAdapter( _
"Select * from authors", conSQL)
Dim datPubs As DataTable = New DataTable( )
adaptSQL.Fill(datPubs, "NewTable")
Creare una DataTable in via programmatica
Dim tblAuthors As DataTable = New DataTable("authors")
tblAuthors.Columns.Add("AuthorID", GetType (Integer))
Scorrere una DataTable
Dim numeroRighe As Int32 = unaTabella.Rows.Count
Dim indiceRiga As Int32
Dim unaRiga As DataRow
For indiceRiga = 0 To numeroRighe - 1
unaRiga = unaTabella.Rows(indiceRiga)
Dim nomeAutore As String = _
unaRiga.Item("au_fname").ToString()
Next
Modificare una DataTable
Aggiungere righe
Dim drNewRow As DataRow = myDataTable.NewRow
'Populate columns
datPubs.Tables("Titles").Rows.Add(drNewRow)
Modificare righe
drChangeRow.BeginEdit( )
drChangeRow("Title") = drChangeRow("Title").ToString & " 1"
drChangeRow.EndEdit( )
Cancellare righe
myDataTable.Rows.Remove(drDelRow)
La classe DataAdapter
E’ il collegamento tra il “mondo” connesso e
quello disconnesso
Può “riempire” DataSet/DataTable avvalendosi
di una connessione chiusa
Dim adaptSQL As New SqlClient.SqlDataAdapter( _
"Select * from authors", conSQL)
Dim datPubs As New DataSet( )
adaptSQL.Fill(datPubs, "miaTabella")
' Accesso ai dati
adaptSQL.Update (datPubs, "miaTabella")
Aggiornare il database
Possiamo ripercuotere le modifiche effettuate al
DataSet sul DB:
Esplicitando il comando di aggiornamento
Dim comm As New SqlClient.SqlCommand("Insert titles" & _
"(title_id, title, type) values(@t_id,@title,@type)")
comm.Parameters.Add("@t_id",SqlDbType.VarChar,6,"title_id")
comm.Parameters.Add("@title",SqlDbType.VarChar,80,"title")
comm.Parameters.Add("@type",SqlDbType.Char,12,"type")
adaptSQL.InsertCommand = comm
adaptSQL.Update(datPubs, "titles")
Generando automaticamente il comando di update
Dim sqlCommBuild As New SqlCommandBuilder(adaptSQL)
MsgBox(sqlCommBuild.GetInsertCommand.CommandText)
adaptSQL.Update(datPubs, "titles")
La classe DataSet
E’ un contenitore disconnesso
E’ assimilabile ad un “vettore di matrici”
Permette di specificare vincoli e relazioni
tra i dati contenuti
E’ accessibile in scrittura
Permette di propagare le modifiche su un
DB
Supporta nativamente la
(de)serializzazione in formato XML
ADO.NET: Approfondimenti
“ADO.NET Primer”, Andrea Saltarello,
workshop “Data Management”.
“ADO.NET 2.0: what’s new”, Andrea
Saltarello, workshop “Data Management”.
Big picture ...
In ADO.NET le sorgenti dati disconnesse non hanno più
il concetto di record corrente.
Il binding di dotnet è gestito da un intermediario tra
controllo e sorgente dati
Qualunque oggetto che implementi IList può essere
utilizzato come sorgente dati
La presenza di un unico intermediario per bindare più
controlli garantisce il sync tra questi
Sync
BindingManagerBase
Data
Sincronizzazione tra controlli
E se non volessimo i due controlli
sincronizzati?
E se volessimo scorrere i dati
indipendentemente sui due controlli?
Risposta: bisogna avere due intermediari
BindingManagerBase
Sync
Data
BindingManagerBase
Simple binding
Associa un qualsiasi tipo ad un controllo in modo da semplificare la
presentazione di un valore e poterlo aggiornare
Proprietà
controllo
DataSource
DataMember
int i=5;
myLabel.DataBindings.Add("Text", i, null);
se è null viene usato
ToString()
Il binding con un singolo elemento implica l'uso di PropertyManager
La proprietà Position sarà sempre 0
Il binding con una lista di elementi implica l'uso di CurrencyManager che ha
il concetto di 'record corrente'.
Si usa Position per navigare le righe mostrate
Non si usa Position per leggere la posizione perchè la lista potrebbe contenere
elementi che non vengono mostrati (es. filtro sulla dataview)
Si usa Current per leggere l'elemento nella lista sottostante (datasource)
Data binding: Approfondimenti
“Windows Forms Databinding”, Raffaele
Rialdi, workshop “Data Management”.
Denkiù!
Links
http://www.ugidotnet.org
http://forum.ugidotnet.org
http://mobile.ugidotnet.org
http://wiki.ugidotnet.org
Fly UP