Da VB a VB.NET Andrea Saltarello [IDevGuro] Corrado Cavalli [DevGuro(Of T)]
-
Upload
carlota-bernasconi -
Category
Documents
-
view
225 -
download
1
Transcript of Da VB a VB.NET Andrea Saltarello [IDevGuro] Corrado Cavalli [DevGuro(Of T)]
Da VB a VB.NETDa VB a VB.NET
Andrea Saltarello [IDevGuro]Andrea Saltarello [IDevGuro]
Corrado Cavalli [DevGuro(Of Corrado Cavalli [DevGuro(Of T)]T)]
SponsorSponsor
Golden migration rule...Golden migration rule... .Non migrare!.Non migrare!
VB.NET è un nuovo linguaggioVB.NET è un nuovo linguaggio
Il wizard fa del suo meglio ma non fa i miracoliIl wizard fa del suo meglio ma non fa i miracoli
Scelta di un Project Scelta di un Project TemplateTemplate
Windows ApplicationWindows ApplicationClass LibraryClass LibraryWindows Control LibraryWindows Control LibraryASP .NET Web Application / Service / ASP .NET Web Application / Service / Control LibraryControl LibraryConsole ApplicationConsole ApplicationWindows ServiceWindows ServiceSmart Device AppSmart Device AppOffice App (VSTO)Office App (VSTO)
Overview del .NET Overview del .NET FrameworkFramework
Visual Studio .NET
Visual Studio .NET
Common Language SpecificationCommon Language Specification
Visual Visual BasicBasic C++C++ C#C# J#J# ……
.NET Framework.NET Framework
Struttura di un ProgettoStruttura di un Progetto
Solution Files (.sln, .suo)Solution Files (.sln, .suo)
Project Files (.vbproj)Project Files (.vbproj)
Local Project ItemsLocal Project ItemsClassi, Form, Moduli, ecc. (.vb)Classi, Form, Moduli, ecc. (.vb)
Web Project ItemsWeb Project ItemsXML Web services (.asmx)XML Web services (.asmx)
Web Form (.aspx)Web Form (.aspx)
Global application classes (.asax)Global application classes (.asax)
Parte #1Parte #1
Il linguaggio Visual Basic .NETIl linguaggio Visual Basic .NET
Definire classiDefinire classi
In VB6, una classe:In VB6, una classe:è un file è un file .cls.clsHa come nome il nome del file (es: Ha come nome il nome del file (es: Customer.clsCustomer.cls))
In VB.NET, una classe:In VB.NET, una classe:È un blocco di codice È un blocco di codice Class…End ClassClass…End ClassIn un unico file ci possono essere più In un unico file ci possono essere più classiclassi
VB.NET=OOP! VB.NET=OOP!
<Scope> Class Car<Scope> Class Car……End ClassEnd Class
File Class1.vbFile Class1.vbPublic Class CarPublic Class Car Public Sub Start()Public Sub Start() End SubEnd SubEnd ClassEnd Class VB 2005VB 2005
File Class2.vbFile Class2.vbPublic Public PartialPartial Class Car Class Car Public Sub Stop()Public Sub Stop() End SubEnd SubEnd ClassEnd Class VB 2005VB 2005
Dim T As New Car()Dim T As New Car()T.Start()T.Start()T.Stop()T.Stop() VB 2005VB 2005
Uso dei CostruttoriUso dei CostruttoriSub NewSub New rimpiazza rimpiazza Class_InitializeClass_Initialize
Viene eseguita quando l’oggetto è istanziatoViene eseguita quando l’oggetto è istanziato
Possiamo specificare più costruttori per la Possiamo specificare più costruttori per la stessa classe (Overload)stessa classe (Overload)
Public Sub New( ) intValue = 1End Sub
Public Sub New(ByVal i As Integer) intValue = iEnd Sub
Distruzione degli oggettiDistruzione degli oggetti
Sub FinalizeSub Finalize rimpiazza l’evento rimpiazza l’evento Class_TerminateClass_TerminateLa usiamo per liberare le risorse usate dall’oggetto La usiamo per liberare le risorse usate dall’oggetto Viene eseguita quando il GC distrugge l’oggettoViene eseguita quando il GC distrugge l’oggetto
Usiamo Usiamo x = Nothingx = Nothing per permettere la Garbage Collection per permettere la Garbage CollectionAttenzione: la distruzione potrebbe non avvenire Attenzione: la distruzione potrebbe non avvenire immediatamente!immediatamente!
Protected Overrides Sub Finalize( ) ‘Rilascio delle risorseEnd Sub
DichiarazioneDichiarazione di Funzioni di Funzioni
Stessa Sintassi di Visual Basic 6.0Stessa Sintassi di Visual Basic 6.0Una classe può contenere metodi con Una classe può contenere metodi con stesso nome e stesso nome e signaturesignature differente differente
una alternativa ai parametri Optionaluna alternativa ai parametri Optionalpiù robusti: errori a compile timepiù robusti: errori a compile time
Non deve esistere ambiguitàNon deve esistere ambiguitàI metodi non possono differire solo per il tipo I metodi non possono differire solo per il tipo di ritorno o argomenti opzionalidi 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àDichiarazione di ProprietàSintassi differente da quella di Visual Basic 6.0Sintassi differente da quella di Visual Basic 6.0
Keyword ReadOnly e WriteOnlyKeyword ReadOnly e WriteOnly
Public ReadOnly Property MyProperty( ) As Integer Get Return _MyProperty End GetEnd Property
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 SetEnd Property
VB.NET=Ereditarietà VB.NET=Ereditarietà
Classi con funzionalità e interfacce molto simili ad un Classi con funzionalità e interfacce molto simili ad un altraaltra
Modifica della classe (errori,interfaccia non congrua)Modifica della classe (errori,interfaccia non congrua)Copia e IncollaCopia e Incolla
Il codice potrebbe non essere disponibileIl codice potrebbe non essere disponibileEredità per delega (favour object composition over inheritance Eredità per delega (favour object composition over inheritance – cit.)– cit.)Parecchio codice per il wrapping della classe internaParecchio codice per il wrapping della classe interna
Car
Car
SuperCaSuperCarr
StartStart
StartStartFasterFaster
EreditarietàEreditarietàCreare una classe che eredita da un altraCreare una classe che eredita da un altra
Eredita Interfaccia e ImplementazioneEredita Interfaccia e ImplementazioneInheritsInheritsNon è necessarioNon è necessario
Source CodeSource CodeStesso linguaggio (C# <-> VB.NET)Stesso linguaggio (C# <-> VB.NET)
Dim sc as New SuperCarDim sc as New SuperCarsc.Start()sc.Start()Sc.Faster()Sc.Faster()
Public Class SuperCarPublic Class SuperCar InheritsInherits Car CarEnd ClassEnd Class
Public Class SuperCarPublic Class SuperCar InheritsInherits Car Car Public Sub TurboPublic Sub Turbo End SubEnd SubEnd ClassEnd Class
Dim sc as New SuperCarDim sc as New SuperCarsc.Start()sc.Start() ‘Car‘Carsc.Faster()sc.Faster() ‘Car‘Carsc.Turbo()sc.Turbo() ‘SuperCar‘SuperCar
EreditarietàEreditarietàConcettiConcetti
La classe da cui si eredita è definita classe La classe da cui si eredita è definita classe BaseBasePosso ereditare da qualsiasi classe .NET (che lo permette)Posso ereditare da qualsiasi classe .NET (che lo permette)Tutte le classi in .NET ereditano da Tutte le classi in .NET ereditano da System.ObjectSystem.ObjectSi definisce una relazione Si definisce una relazione “Is a”“Is a” (é un) (é un)
In .NET tutto è ObjectIn .NET tutto è Object
Dim c as Car= New SuperCarDim c as Car= New SuperCarc.Start()c.Start()c.Turbo()c.Turbo() ‘‘ErroreErrore
Public Class SuperCarPublic Class SuperCar InheritsInherits Car Car Public Sub TurboPublic Sub Turbo End SubEnd SubEnd ClassEnd Class
Una classe può ereditare da una sola classe baseUna classe può ereditare da una sola classe baseSingle InheritanceSingle Inheritance
OverrideOverrideLa classe che eredita può modificare il comportamento della classe baseLa classe che eredita può modificare il comportamento della classe base
Ridefinendone i metodi/proprieta/eventiRidefinendone i metodi/proprieta/eventiLa classe base deve permetterne la redifinizioneLa classe base deve permetterne la redifinizioneOverridableOverridable
Public Class Car Public Class Car Public Public OverridableOverridable Sub Faster Sub Faster Console.WriteLine(“base”)Console.WriteLine(“base”) End SubEnd SubEnd ClassEnd Class Public Class SuperCarPublic Class SuperCar
InheritsInherits Car Car Public Public OverridesOverrides Sub Faster Sub Faster Console.WriteLine(“Inherited”)Console.WriteLine(“Inherited”) End SubEnd SubEnd ClassEnd Class
Dim c as New SuperCarDim c as New SuperCarc.Faster()c.Faster() ‘‘InheritedInherited
OverrideOverrideUn metodo dichiarato Un metodo dichiarato OverridesOverrides::
E’ automaticamente OverridableE’ automaticamente OverridableSi può usare Si può usare NotOverridableNotOverridable per modificarne il comportamento per modificarne il comportamento
Public Class SuperCar: Public Class SuperCar: InheritsInherits Car Car Public Public NotOverridableNotOverridable OverridesOverrides Sub Faster Sub Faster Console.WriteLine(“Inherited”)Console.WriteLine(“Inherited”) End SubEnd SubEnd ClassEnd Class
MyBaseMyBaseRappresenta la classe da cui si sta ereditando Rappresenta la classe da cui si sta ereditando
Public Class SuperCar: Public Class SuperCar: InheritsInherits Car Car Public Overrides ReadOnly Property Model as StringPublic Overrides ReadOnly Property Model as String Return Return MyBase.ModelMyBase.Model + “ Super” + “ Super” End SubEnd SubEnd ClassEnd Class
OverrideOverrideI costruttori non vengono ereditatiI costruttori non vengono ereditati
No problem se non avete dei costruttori parametrici (usa default)No problem se non avete dei costruttori parametrici (usa default)Dovete invocarli esplicitamente (prima istruzione)Dovete invocarli esplicitamente (prima istruzione)
Public Class SuperCar: Public Class SuperCar: InheritsInherits Car Car Public Sub New (cilindrata as Integer)Public Sub New (cilindrata as Integer) MyBase.New(cilindrata)MyBase.New(cilindrata) ‘Inizializzo la classe base‘Inizializzo la classe base End SubEnd SubEnd ClassEnd Class
Public Class CarPublic Class Car Public Sub New (cilindrata as Integer)Public Sub New (cilindrata as Integer) End SubEnd SubEnd ClassEnd Class
Public Class Car Public Class Car Private Sub IncreaseSpeedPrivate Sub IncreaseSpeed MeMe.Faster().Faster() End SubEnd SubEnd ClassEnd Class
Override, classe base e MeOverride, classe base e MeQuando associate un istanza di una classe ereditata ad una Quando associate un istanza di una classe ereditata ad una variabile di tipo base, la classe base “vede” l’implementazione variabile di tipo base, la classe base “vede” l’implementazione dei metodi della classe ereditatadei metodi della classe ereditata
Public Class Car Public Class Car Public Public OverridableOverridable Sub Faster Sub Faster Console.WriteLine(“base”)Console.WriteLine(“base”) End SubEnd SubEnd ClassEnd Class Public Class SuperCar: Public Class SuperCar: InheritsInherits Car Car
Public Public OverridesOverrides Sub Faster Sub Faster Console.WriteLine(“Inherited”)Console.WriteLine(“Inherited”) End SubEnd SubEnd ClassEnd Class
Dim c as Car= New SuperCarDim c as Car= New SuperCarc.Faster()’c.Faster()’ InheritedInherited
MeMe non indicanon indica il contesto corrente il contesto corrente
Public Class Car Public Class Car Private Sub IncreaseSpeedPrivate Sub IncreaseSpeed MyClassMyClass.Faster().Faster() End SubEnd SubEnd ClassEnd Class
MyClassMyClassMyClassMyClass permette di specificare che il contesto di esecuzione permette di specificare che il contesto di esecuzione sia quello della classe base e non quello di eventuali overrides sia quello della classe base e non quello di eventuali overrides in classi ereditanti da essain classi ereditanti da essa
Viene eseguito il metodo Faster della classe CarViene eseguito il metodo Faster della classe CarNon disponibile in C#Non disponibile in C#
Public Class SuperCar: Public Class SuperCar: InheritsInherits Car Car Public Public ShadowsShadows Sub Faster Sub Faster Console.WriteLine(“Inherited”)Console.WriteLine(“Inherited”) End SubEnd SubEnd ClassEnd Class
ShadowsShadowsOverrides funziona se il metodo della classe base è virtualOverrides funziona se il metodo della classe base è virtual
Potrebbe non esserlo (I metodi Overridable sono più ‘lenti’)Potrebbe non esserlo (I metodi Overridable sono più ‘lenti’)Potremmo non poterlo modificarePotremmo non poterlo modificare
ShadowsShadowsPermette di ridefinire metodi già presenti nella classe basePermette di ridefinire metodi già presenti nella classe base
Sono a tutti gli effetti delle nuove implementazioniSono a tutti gli effetti delle nuove implementazioniSono ignorate dalla classe base (no ereditarietà)Sono ignorate dalla classe base (no ereditarietà)Va usato per ridefinire membri SharedVa usato per ridefinire membri Shared
Dim c as Car= New SuperCarDim c as Car= New SuperCarc.Faster()’c.Faster()’ basebase
In alcuni casi potremmo non volere che qualcuno erediti la nostra classeIn alcuni casi potremmo non volere che qualcuno erediti la nostra classe
NotInheritable e MustInheritNotInheritable e MustInheritNotInheritableNotInheritable
Indica che la classe non è ereditabile Indica che la classe non è ereditabile (sealed class)(sealed class)
Public Public NotInheritableNotInheritable Class Car Class Car End ClassEnd Class
Public Class SuperCarPublic Class SuperCar InheritsInherits Car ‘ Car ‘ErroreErroreEnd ClassEnd Class
MustInheritMustInheritNon può essere istanziata Non può essere istanziata (abstract class)(abstract class)Può essere usata solo Può essere usata solo ereditandoereditando da essa da essaSpesso contiene dei metodi definiti Spesso contiene dei metodi definiti MustOverrideMustOverridePermette di definire delle classi che hanno funzionalità parzialePermette di definire delle classi che hanno funzionalità parziale
Public Public MustInheritMustInherit Class Car Class Car Public Public MustOverrideMustOverride Sub Faster Sub Faster End SubEnd SubEnd ClassEnd Class
Classe Astratta: CollectionBaseClasse Astratta: CollectionBaseSystem.Collection.CollectionBaseSystem.Collection.CollectionBase
Permette di creare collezioni tipizzatePermette di creare collezioni tipizzate
Public Class Cars : Inherits Public Class Cars : Inherits CollectionBaseCollectionBase Public Sub Public Sub AddAdd(ByVal item As (ByVal item As CarCar)) MyBase.InnerListMyBase.InnerList.Add(item).Add(item) End SubEnd Sub
DefaultDefault Property Item(ByVal index As Integer) As Property Item(ByVal index As Integer) As CarCar GetGet Return DirectCast(Return DirectCast(MyBase.InnerList(index)MyBase.InnerList(index), Car), Car) End GetEnd Get Set(ByVal Value As Car)Set(ByVal Value As Car) MyBase.InnerList(index) = ValueMyBase.InnerList(index) = Value End SetEnd Set End PropertyEnd PropertyEnd ClassEnd Class Dim l as New Cars()Dim l as New Cars()
l.Add(new Car)l.Add(new Car) ‘‘okokl.Add (New Truck) l.Add (New Truck) ‘‘ErroreErrore
VB 2005 - GenericsVB 2005 - GenericsPermettono di definire dei tipi “generici” che verrano Permettono di definire dei tipi “generici” che verrano “completati” a compile time“completati” a compile time
Public Class CarPublic Class CarPrivate _Navigator As Private _Navigator As TT
Public ReadOnly Property Navigator As Public ReadOnly Property Navigator As TTGetGet Return _Navigator Return _Navigator End GetEnd GetEnd ClassEnd Class
PlaceholderPlaceholderPublic Class CarPublic Class Car(Of T)(Of T)Private _Navigator As Private _Navigator As TT
Public ReadOnly Property Navigator As Public ReadOnly Property Navigator As TTGetGet Return _Navigator Return _Navigator End GetEnd GetEnd ClassEnd Class
Public Class TomTomPublic Class TomTom Public Sub RouteTo():End SubPublic Sub RouteTo():End SubEnd ClassEnd Class
Public Class GarminPublic Class Garmin Public Sub NavigateTo():End Sub Public Sub NavigateTo():End SubEnd ClassEnd Class
Dim Car1 As New Car(Of TomTom)Dim Car1 As New Car(Of TomTom)Dim Car2 As New Car(Of Garmin)Dim Car2 As New Car(Of Garmin)
Car1.Navigator.Car1.Navigator.
VB 2005 – Generics CollectionsVB 2005 – Generics Collections
Public Class ListPublic Class List Private elements() As ObjectPrivate elements() As Object Private count As IntegerPrivate count As Integer
Public Sub Add(ByVal element As Object)Public Sub Add(ByVal element As Object) If count = elements.Length Then Resize(count * 2)If count = elements.Length Then Resize(count * 2) elements(count) = element : count += 1elements(count) = element : count += 1 End SubEnd Sub
Public Default Property Item(ByVal Index _Public Default Property Item(ByVal Index _ As Integer) As ObjectAs Integer) As Object Get Get
Return elements(index) Return elements(index) End GetEnd Get Set (value as object) Set (value as object) elements(index) = value elements(index) = value End SetEnd Set End Property End Property End ClassEnd Class
Dim intList As New List()Dim intList As New List()
intList.Add(1) ‘ Boxing!intList.Add(1) ‘ Boxing!intList.Add(2) ‘ Boxing!intList.Add(2) ‘ Boxing!intList.Add(“Pippo") ‘ No error… intList.Add(“Pippo") ‘ No error…
i = CInt(intList(0)) ‘ Richiesto casti = CInt(intList(0)) ‘ Richiesto cast
Public Class ListPublic Class List(Of T)(Of T) Private elements() As Private elements() As TT Private count As IntegerPrivate count As Integer
Public Sub Add(ByVal element As Public Sub Add(ByVal element As TT)) If count = elements.Length Then Resize(count * 2)If count = elements.Length Then Resize(count * 2) elements(count) = element : count += 1elements(count) = element : count += 1 End SubEnd Sub
Public Default Property Item(ByVal Index _Public Default Property Item(ByVal Index _ As Integer) As As Integer) As TT Get Get
Return elements(index) Return elements(index) End GetEnd Get Set (value as Set (value as TT) ) elements(index) = value elements(index) = value End SetEnd Set End PropertyEnd PropertyEnd ClassEnd Class
Dim intList As New List(Of Int32)Dim intList As New List(Of Int32)
intList.Add(1) ‘ No Boxing!intList.Add(1) ‘ No Boxing!intList.Add(2) ‘ No Boxing!intList.Add(2) ‘ No Boxing!intList.Add(“Pippo") ‘ Error… intList.Add(“Pippo") ‘ Error…
i = intList(0)i = intList(0) ‘ Non serve castare ‘ Non serve castare
VB 2005 – Generics MethodsVB 2005 – Generics Methods
Dim X As Int32 = 3Dim X As Int32 = 3Dim Y As Int32 = 4Dim Y As Int32 = 4
Dim Z As Int32 = IIf(X>Y,X,Y) ‘Dim Z As Int32 = IIf(X>Y,X,Y) ‘ErrorError
Dim Z As Int32 = MyIIF(Of Int32)(X>Y,X,Y) ‘No cast!Dim Z As Int32 = MyIIF(Of Int32)(X>Y,X,Y) ‘No cast!
Dim Z As Int32 = MyIIF(X>Y,X,Y) ‘ Type inferencingDim Z As Int32 = MyIIF(X>Y,X,Y) ‘ Type inferencing
Public Function MyIIF (Of T)(cond As Boolean, _Public Function MyIIF (Of T)(cond As Boolean, _trueP As T, falseP As T) As TtrueP As T, falseP As T) As T If (cond) Then If (cond) Then Return trueP Return trueP ElseElse Return falseP Return falseP End If End IfEnd SubEnd Sub
VB 2005 – Generics ConstraintsVB 2005 – Generics ConstraintsPublic Class CarPublic Class Car(Of T)(Of T)Private _Navigator As Private _Navigator As TT
Public ReadOnly Property Navigator As Public ReadOnly Property Navigator As TTGetGet Return _Navigator Return _Navigator End GetEnd GetEnd ClassEnd Class
Dim Car1 As New Car(Of TomTom)Dim Car1 As New Car(Of TomTom)Car1.Navigator.RouteTo()’ Car1.Navigator.RouteTo()’ ErrorError
Public Class Car _Public Class Car _(Of T As(Of T As {New,BaseClass,I1,I2,Class,Structure}{New,BaseClass,I1,I2,Class,Structure}))Private _Navigator As New Private _Navigator As New TT
Public ReadOnly Property Navigator As Public ReadOnly Property Navigator As TTGetGet Return _Navigator Return _Navigator End GetEnd GetEnd ClassEnd Class
Public Class CarPublic Class Car(Of T)(Of T)Private _Navigator As Private _Navigator As NewNew TT
Public ReadOnly Property Navigator As Public ReadOnly Property Navigator As TTGetGet Return _Navigator Return _Navigator End GetEnd GetEnd ClassEnd Class
Public Class CarPublic Class Car(Of T (Of T As NewAs New))Private _Navigator As New Private _Navigator As New TT
Public ReadOnly Property Navigator As Public ReadOnly Property Navigator As TTGetGet Return _Navigator Return _Navigator End GetEnd GetEnd ClassEnd Class
VB.NET: ApprofondimentiVB.NET: Approfondimenti
““Da VB a VB.NET”, Andrea Saltarello, Da VB a VB.NET”, Andrea Saltarello, workshop 14/11/2001workshop 14/11/2001
““Language Revolution”, Corrado Cavalli e Language Revolution”, Corrado Cavalli e Raffaele Rialdi, Raffaele Rialdi, ““WhidbeyWhidbey workshop” workshop”
An Introduction to Visual Basic 2005, Jay An Introduction to Visual Basic 2005, Jay Roxe e Sean Draine, Roxe e Sean Draine, “Whidbey (Reloaded) workshop”“Whidbey (Reloaded) workshop”
Classi AttributoClassi AttributoLe classi attributo:Le classi attributo:
dal punto di vista dell’utilizzatore, sono espressioni utili per dal punto di vista dell’utilizzatore, sono espressioni utili per decoraredecorare porzioni di codice porzioni di codiceDal punto di vista del realizzatore, sono classi che specializzano Dal punto di vista del realizzatore, sono classi che specializzano System.AttributeSystem.Attribute
E’ raccomandato l’uso del suffisso E’ raccomandato l’uso del suffisso AttributeAttribute nella definizione del nella definizione del nome delle suddette classinome delle suddette classi
Il suffisso può essere omesso in fase di Il suffisso può essere omesso in fase di decorazionedecorazione del codice del codice
Public Class ReportManagerPublic Class ReportManager <Obsolete(“Dovresti usare PrintLabel(Int32)”)> _<Obsolete(“Dovresti usare PrintLabel(Int32)”)> _ Public Sub PrintLabel()Public Sub PrintLabel() PrintLabel(1)PrintLabel(1) End SubEnd Sub
Public Sub PrintLabel(ByVal copies As Integer)Public Sub PrintLabel(ByVal copies As Integer) End SubEnd SubEnd ClassEnd Class
Attributi: approfondimentiAttributi: approfondimenti
““Componenti "Alternativi": le classi Componenti "Alternativi": le classi Attributo”, Andrea Saltarello, Attributo”, Andrea Saltarello, workshop “workshop “ComponentComponent DevelopmentDevelopment””
Parte #2Parte #2
VB.NET vs. Windows FormsVB.NET vs. Windows Forms
VB6VB6Aggiunta di un file .res al progettoAggiunta di un file .res al progetto
Utilizzo del resource editorUtilizzo del resource editor
Localizzare testo usandoLocalizzare testo usandoLoadResStringLoadResString
LoadResPictureLoadResPicture
LoadResDataLoadResData
No local/region awareNo local/region aware
Difficile integrare cultureDifficile integrare culturediversediverse
Difficile estendere laDifficile estendere lalocalizzazionelocalizzazione
No locale adaptive UINo locale adaptive UI
Localizzazione in VB6Localizzazione in VB6
VB.NETVB.NETSi appoggia su files xml (.resx)Si appoggia su files xml (.resx)
ResGen.exe .resx -> .resources ResGen.exe .resx -> .resources
ResourceManagerResourceManagerCerca le assembly satellite utilizzando la cultura della UICerca le assembly satellite utilizzando la cultura della UI
ProbingProbing<language-culture><language-culture>
<language><language>
Neutral / Default cultureNeutral / Default culture
ToolsToolsWinRes.exe WinRes.exe
Lutz Roeder’s Resourcer (http://www.aisto.com/roeder/dotnet/)Lutz Roeder’s Resourcer (http://www.aisto.com/roeder/dotnet/)
Al.exeAl.exe
Localizzazione in .NETLocalizzazione in .NET
Localizzazione: ApprofondimentiLocalizzazione: Approfondimenti
““Applicazioni Windows Forms Applicazioni Windows Forms localizzate”, Corrado Cavalli, localizzate”, Corrado Cavalli, articoloarticolo..
Applicazioni MDIApplicazioni MDI
Proprietà Proprietà IsMdiContainerIsMdiContainer = True per = True per “promuovere” un form allo stato di “promuovere” un form allo stato di contenitore MDIcontenitore MDI
Nessun limite sul numero di form MDI per Nessun limite sul numero di form MDI per applicazioneapplicazione
Proprietà Proprietà MdiParentMdiParent = = mdiformmdiform per per “incastrare” il form MDI child“incastrare” il form MDI childun form MDI può ospitare *qualsiasi* un form MDI può ospitare *qualsiasi* controllo sulla sua superficiecontrollo sulla sua superficie
Alcuni controlli (es: Menu, ListBox e Alcuni controlli (es: Menu, ListBox e ComboBox) espongono la proprietà ComboBox) espongono la proprietà DrawModeDrawMode, che può essere , che può essere impostata aimpostata a::
NormalNormalOwnerDrawFixedOwnerDrawFixedOwnerDrawVariableOwnerDrawVariable
L'evento L'evento DrawItemDrawItem riceve un riceve un riferimento all’elemento (es: l’indice) riferimento all’elemento (es: l’indice) e un oggetto e un oggetto GraphicsGraphics
Controlli Owner drawnControlli Owner drawn
DelegateDelegate
Le delegate sono dei puntatori a Le delegate sono dei puntatori a funzione:funzione:
ManagedManaged. Non abbiamo in mano un . Non abbiamo in mano un vero puntatore a funzione, ma un vero puntatore a funzione, ma un oggetto in grado di rintracciarlo. Il GC oggetto in grado di rintracciarlo. Il GC non ci preoccupa: CLR e FX sono in non ci preoccupa: CLR e FX sono in combutta e mantengono valido il combutta e mantengono valido il “puntatore”“puntatore”
type-safetype-safe. Le funzioni devono . Le funzioni devono rispettare la firma della delegaterispettare la firma della delegate
MultithreadingMultithreading
Il framework offre la classe Thread, Il framework offre la classe Thread, che accetta in ingresso una istanza che accetta in ingresso una istanza della delegate ThreadStartdella delegate ThreadStart
Asyncronous ProgrammingAsyncronous ProgrammingIl cliente vuole applicazioni “veloci”Il cliente vuole applicazioni “veloci”
Ottimizzare la velocità apparenteOttimizzare la velocità apparente
Collo di bottiglia... Attendere prego... Applicazione FreezedCollo di bottiglia... Attendere prego... Applicazione Freezed
Application.DoEvents()Application.DoEvents()
Eseguire l’operazione in un thread separatoEseguire l’operazione in un thread separato
Non è consentito accedere a controlli Windows da Non è consentito accedere a controlli Windows da threads diversi da quello in cui il controllo è stato threads diversi da quello in cui il controllo è stato creatocreato
Gli unici metodi thread-safe di un controllo windows sonoGli unici metodi thread-safe di un controllo windows sonoInvokeInvoke
BeginInvokeBeginInvoke
EndInvokeEndInvoke
CreateGraphicsCreateGraphics
ISyncronizeInvokeISyncronizeInvokeInvokeRequired,Invoke,BeginInvoke,EndInvokeInvokeRequired,Invoke,BeginInvoke,EndInvoke
ControlControl implementa ISyncronizeInvoke implementa ISyncronizeInvoke
InvokeRequiredInvokeRequired
public readonly property InvokeRequired() as booleanpublic readonly property InvokeRequired() as boolean getget Dim procId as IntegerDim procId as Integer Dim WinThId = GetWindowThreadProcessId(Me.Handle, procId) Dim WinThId = GetWindowThreadProcessId(Me.Handle, procId) return return AppDomain.GetCurrentThreadIdAppDomain.GetCurrentThreadId()<>WinThId()<>WinThId end getend getEnd propertyEnd property
Ritorna True se il thread che invoca la proprietà Ritorna True se il thread che invoca la proprietà è diverso da quello che ha creato il controlloè diverso da quello che ha creato il controllo
Non siamo sicuri se è safe accedere al controlloNon siamo sicuri se è safe accedere al controllo
Metodi always safe Metodi always safe
Asyncronous DelegatesAsyncronous DelegatesI delegates possono essere utilizzati per eseguire I delegates possono essere utilizzati per eseguire operazioni asincroneoperazioni asincrone
BeginInvokeBeginInvokeRitorna IAsyncResultRitorna IAsyncResult
IAsyncResult.IAsyncResult.IsCompletedIsCompleted
BeginInvoke (AsyncCallback,Object)BeginInvoke (AsyncCallback,Object)Invoca AsyncCallback al termine dell’operazioneInvoca AsyncCallback al termine dell’operazione
AsyncCallback(ByVal ar as IAsyncResult)AsyncCallback(ByVal ar as IAsyncResult)
Object viene passato alla procedura di callbackObject viene passato alla procedura di callback
In AsyncCallback deve essere invocato In AsyncCallback deve essere invocato EndInvokeEndInvoke
AsyncCallback viene invocata AsyncCallback viene invocata in un thread separatoin un thread separatoIl thread proviene dal ThreadPool Il thread proviene dal ThreadPool
BeginInvoke/EndInvoke posson generare delle eccezioniBeginInvoke/EndInvoke posson generare delle eccezioni
Non è possibile interropere BeginInvokeNon è possibile interropere BeginInvoke
GUI Asincrona: ApprofondimentiGUI Asincrona: Approfondimenti
““Accesso Thread-Safe a controlli Accesso Thread-Safe a controlli Windows FormsWindows Forms”, Corrado Cavalli, ”, Corrado Cavalli, articoloarticolo..
Parte #3Parte #3
Accesso ai datiAccesso ai dati
PrerequisitiPrerequisiti
v1.x: deploy manuale di MDAC v1.x: deploy manuale di MDAC 2.7+2.7+v2.0: non necessitano di MDAC:v2.0: non necessitano di MDAC:
Classi base, comuni Classi base, comuni (System.Data.Common) e disconnesse(System.Data.Common) e disconnesse.NET managed provider per SQL Server e .NET managed provider per SQL Server e OracleOracle
v2.0: usano MDAC, senza v2.0: usano MDAC, senza particolari requisiti:particolari requisiti:
Managed provider OLEDB e ODBCManaged provider OLEDB e ODBCVanno bene le versioni 2.6, 2.7, 2.8 o… 9.0Vanno bene le versioni 2.6, 2.7, 2.8 o… 9.0
Struttura di ADO .NETStruttura di ADO .NET
ADO .NET è composto da:ADO .NET è composto da:Namespace Namespace System.DataSystem.Data: racchiude le primitive : racchiude le primitive indipendenti dalla tipologia di base dati. indipendenti dalla tipologia di base dati.
Sono tutte disconnesseSono tutte disconnesse
.NET Managed Provider: implementano le .NET Managed Provider: implementano le primitive necessarie all’accesso a primitive necessarie all’accesso a specifiche specifiche basi basi datidati
System.Data.SqlClientSystem.Data.SqlClient per l’accesso a SQL Server 7+ per l’accesso a SQL Server 7+
System.Data.OleDbSystem.Data.OleDb per connettersi usando un OleDb per connettersi usando un OleDb Provider Provider
System.Data.OracleClientSystem.Data.OracleClient
System.Data.OdbcSystem.Data.Odbc
Common Provider ModelCommon Provider Model
ADO.NET v1.0/1.1 è basato su ADO.NET v1.0/1.1 è basato su alcune interfaccealcune interfacce• E’ problematico scrivere codice indipendente E’ problematico scrivere codice indipendente
dalla base datidalla base dati
ADO .NET 2.0 è basato su classi ADO .NET 2.0 è basato su classi base condivise dai providerbase condivise dai provider• E’ una estensione, non introduce E’ una estensione, non introduce
incompatibilitàincompatibilità• La sintassi SQL è comunque La sintassi SQL è comunque specificaspecifica per la per la
base dati!base dati!• Architettura basata sul pattern FactoryArchitettura basata sul pattern Factory
.NET Data Providers.NET Data Providers
Implementano un insieme comune di Implementano un insieme comune di interfacce esponendo le classi:interfacce esponendo le classi:
Connection: permette la connessione ad Connection: permette la connessione ad una base datiuna base dati
Command: permette l’esecuzione di Command: permette l’esecuzione di comandi SQL e comandi SQL e Stored ProcedureStored Procedure
DataReader: implementa un cursore DataReader: implementa un cursore forward-only, read-only, client sideforward-only, read-only, client side
DataAdapter: permette di “riempire” un DataAdapter: permette di “riempire” un contenitore disconnessocontenitore disconnesso
Classe ConnectionClasse Connection
Simile ad ADO Simile ad ADO old-styleold-style
La Connection String:La Connection String:Può essere specificata mediante un Può essere specificata mediante un costruttore costruttore parametricoparametrico
Utilizza le stesse keyword di ADODBUtilizza le stesse keyword di ADODB
Richiede attenzione nella specifica del Richiede attenzione nella specifica del Provider:Provider:SqlClient SqlClient nonnon lo accetta lo accetta
System.Data.OleDb non supporta ODBCSystem.Data.OleDb non supporta ODBC
Dim conSQL As New SqlConnection( )conSQL.ConnectionString = "Integrated Security=True;" & _
"Data Source=LocalHost;Initial Catalog=Pubs;"conSQL.Open( )
Classe CommandClasse Command
Possiamo creare un comando:Possiamo creare un comando:Mediante il costruttoreMediante il costruttore
Mediante metodo Mediante metodo CreateCommandCreateCommand
Possiamo eseguire un comando mediante i Possiamo eseguire un comando mediante i metodi:metodi:
ExecuteReaderExecuteReader: restituisce il DataReader in base ad : restituisce il DataReader in base ad una queryuna query
ExecuteScalarExecuteScalar: è il metodo preferibile se il risultato : è il metodo preferibile se il risultato è un è un singletonsingleton
ExecuteNonQueryExecuteNonQuery: esegue un comando di azione: esegue un comando di azione
Dim commSQL As New SqlCommand( )commSQL.Connection = conSQLcommSQL.CommandText = "Select Count(*) from Authors"MessageBox.Show(commSQL.ExecuteScalar( ).ToString)
Invocare Stored ProcedureInvocare Stored Procedure
1.1. Creare un oggetto Creare un oggetto CommandCommand2.2. Impostare Impostare CommandTypeCommandType al valore al valore
StoredProcedureStoredProcedure3.3. Impostare la proprietà Impostare la proprietà CommandTextCommandText4.4. Usare il metodo Usare il metodo AddAdd per creare e aggiungere per creare e aggiungere
parametriparametri5.5. Impostare la proprietà Impostare la proprietà ParameterDirectionParameterDirection6.6. Invocare Invocare ExecuteReaderExecuteReader7.7. Consumare i record, e chiudere il Consumare i record, e chiudere il DataReaderDataReader8.8. Leggere i parametri di output e il valore di Leggere i parametri di output e il valore di
ritornoritorno
Usare un DataReaderUsare un DataReader
Per usare un DataReader, possiamo:Per usare un DataReader, possiamo:Avanzare alla posizione successiva mediante il Avanzare alla posizione successiva mediante il metodo metodo Read()Read(), che ritorna True finchè non si , che ritorna True finchè non si sono consumati tutti i datisono consumati tutti i dati
Leggere i valori dei campi mediante la proprietà Leggere i valori dei campi mediante la proprietà Item, oppure mediante i metodi Item, oppure mediante i metodi GetGetXYZXYZ()()
Un DataReader impegna la propria Un DataReader impegna la propria connessione, quindi:connessione, quindi:
Non è possibile utilizzarla per eseguire comandiNon è possibile utilizzarla per eseguire comandi
Dobbiamo ricordarci di chiuderlo mediante il Dobbiamo ricordarci di chiuderlo mediante il metodo metodo Close()Close()
M.A.R.S.M.A.R.S.
In v2.0, Multiple Active Results Sets:In v2.0, Multiple Active Results Sets:
Mantiene disponibile una connessione quando Mantiene disponibile una connessione quando apriamo un SqlDataReader al fine di poter:apriamo un SqlDataReader al fine di poter:
Eseguire un’altra query per ottenere un Eseguire un’altra query per ottenere un DataReader/XmlReaderDataReader/XmlReader
Eseguire comandi DMLEseguire comandi DML
permette differenti result set contemporaeamente permette differenti result set contemporaeamente attivi:attivi:
alternare fetch ad ogni readeralternare fetch ad ogni reader
Alternare query che non restituiscono readerAlternare query che non restituiscono reader
Mediante MARS, è sufficiente una sola connessione se:Mediante MARS, è sufficiente una sola connessione se:I dati risiedono nello stesso databaseI dati risiedono nello stesso databaseUsiamo SQL Server 2005/MDAC9Usiamo SQL Server 2005/MDAC9
M.A.R.S.M.A.R.S.
Dim parentReader As DataReader = Dim parentReader As DataReader = Command1.ExecuteReader()Command1.ExecuteReader()While parentReader.Read()While parentReader.Read() ' process parent row data here' process parent row data here ' then get rowset from child table' then get rowset from child table Command2.Parameters("@id").Value = parentReader("id")Command2.Parameters("@id").Value = parentReader("id") Dim childReader As DataReader = Dim childReader As DataReader = Command2.ExecuteReader()Command2.ExecuteReader() ' process child rows here' process child rows here childReader.Close()childReader.Close()End WhileEnd WhileparentReader.Close()parentReader.Close()
La classe DataTableLa classe DataTable
E’ il contenitore dati disconnessi di E’ il contenitore dati disconnessi di ADO.NETADO.NET
La classe La classe DataTableDataTable espone le espone le proprietà:proprietà:
Columns: è una collezione di istanze di Columns: è una collezione di istanze di DataColumnDataColumn
Rows: è una collezione di istanze della Rows: è una collezione di istanze della classe classe DataRowDataRow
Una istanza della classe DataRow:Una istanza della classe DataRow:Mette a disposizione il contenuto delle Mette a disposizione il contenuto delle proprie colonne mediante la proprietà proprie colonne mediante la proprietà ItemItem
Popolare una DataTablePopolare una DataTable
Popolare una DataTable accedendo ad un Popolare una DataTable accedendo ad un RDBMSRDBMS
Creare una DataTable in via programmaticaCreare una DataTable in via programmatica
Dim tblAuthors As DataTable = New DataTable("authors")tblAuthors.Columns.Add("AuthorID", GetType (Integer))
Dim adaptSQL As New SqlClient.SqlDataAdapter( _"Select * from authors", conSQL)
Dim datPubs As DataTable = New DataTable( )adaptSQL.Fill(datPubs, "NewTable")
Scorrere una DataTableScorrere una DataTable
Dim numeroRighe As Int32 = unaTabella.Rows.CountDim indiceRiga As Int32Dim unaRiga As DataRow
For indiceRiga = 0 To numeroRighe - 1unaRiga = unaTabella.Rows(indiceRiga)Dim nomeAutore As String = _
unaRiga.Item("au_fname").ToString()Next
Modificare una DataTableModificare una DataTableAggiungere righeAggiungere righe
Modificare righeModificare righe
Cancellare righeCancellare righe
myDataTable.Rows.Remove(drDelRow)
drChangeRow.BeginEdit( )drChangeRow("Title") = drChangeRow("Title").ToString & " 1"drChangeRow.EndEdit( )
Dim drNewRow As DataRow = myDataTable.NewRow 'Populate columnsdatPubs.Tables("Titles").Rows.Add(drNewRow)
La classe DataAdapterLa classe DataAdapter
E’ il collegamento tra il “mondo” E’ il collegamento tra il “mondo” connesso e quello disconnessoconnesso e quello disconnesso
Può “riempire” DataSet/DataTable Può “riempire” DataSet/DataTable avvalendosi di una connessione avvalendosi di una connessione chiusachiusa
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 databaseAggiornare il databasePossiamo ripercuotere le modifiche effettuate al Possiamo ripercuotere le modifiche effettuate al DataSet sul DB:DataSet sul DB:
Esplicitando il comando di aggiornamentoEsplicitando il comando di aggiornamento
Generando automaticamente il comando di Generando automaticamente il comando di updateupdate
Dim sqlCommBuild As New SqlCommandBuilder(adaptSQL)MsgBox(sqlCommBuild.GetInsertCommand.CommandText)adaptSQL.Update(datPubs, "titles")
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 = commadaptSQL.Update(datPubs, "titles")
La classe DataSetLa classe DataSet
E’ un contenitore disconnessoE’ un contenitore disconnesso
E’ assimilabile ad un “vettore di E’ assimilabile ad un “vettore di matrici”matrici”
Permette di specificare vincoli e Permette di specificare vincoli e relazioni tra i dati contenutirelazioni tra i dati contenuti
E’ accessibile in scritturaE’ accessibile in scrittura
Permette di propagare le modifiche Permette di propagare le modifiche su un DBsu un DB
Supporta nativamente la Supporta nativamente la (de)serializzazione in formato XML(de)serializzazione in formato XML
ADO.NET: ApprofondimentiADO.NET: Approfondimenti
““ADO.NET Primer”, Andrea ADO.NET Primer”, Andrea Saltarello, Saltarello, workshop “Data Management”.workshop “Data Management”.
““ADO.NET 2.0: what’s new”, Andrea ADO.NET 2.0: what’s new”, Andrea Saltarello, Saltarello, workshop “Data Management”.workshop “Data Management”.
Big picture ...Big picture ...
In ADO.NET le sorgenti dati disconnesse non In ADO.NET le sorgenti dati disconnesse non hanno più il concetto di hanno più il concetto di record correnterecord corrente..Il binding di dotnet è gestito da un Il binding di dotnet è gestito da un intermediario intermediario tra controllo e sorgente datitra controllo e sorgente datiQualunque oggetto che implementi IList può Qualunque oggetto che implementi IList può essere utilizzato come sorgente datiessere utilizzato come sorgente datiLa presenza di un unico intermediario per La presenza di un unico intermediario per bindare più controlli garantisce il sync tra questibindare più controlli garantisce il sync tra questi
BindingManagerBaseBindingManagerBase DataSync
Sincronizzazione tra Sincronizzazione tra controllicontrolli
E se non volessimo i due controlli E se non volessimo i due controlli sincronizzati?sincronizzati?
E se volessimo scorrere i dati E se volessimo scorrere i dati indipendentemente sui due controlli?indipendentemente sui due controlli?
Risposta: bisogna avere Risposta: bisogna avere duedue intermediariintermediari
DataSync
BindingManagerBaseBindingManagerBase
BindingManagerBaseBindingManagerBase
Simple bindingSimple binding
Associa un qualsiasi tipo ad un controllo in modo da semplificare la Associa un qualsiasi tipo ad un controllo in modo da semplificare la presentazione di un valore e poterlo aggiornarepresentazione di un valore e poterlo aggiornare
Il binding con un Il binding con un singolo elementosingolo elemento implica l'uso di implica l'uso di PropertyManagerPropertyManager
La proprietà Position sarà sempre 0La proprietà Position sarà sempre 0
Il binding con una Il binding con una lista di elementilista di elementi implica l'uso di implica l'uso di CurrencyManagerCurrencyManager che ha il concetto di ' che ha il concetto di 'record correnterecord corrente'.'.
Si usa Position per navigare le righe mostrateSi usa Position per navigare le righe mostrate
Non si usa Position per leggere la posizione perchè la lista potrebbe Non si usa Position per leggere la posizione perchè la lista potrebbe contenere elementi che non vengono mostrati (es. filtro sulla dataview)contenere elementi che non vengono mostrati (es. filtro sulla dataview)
Si usa Current per leggere l'elemento nella lista sottostante (datasource)Si usa Current per leggere l'elemento nella lista sottostante (datasource)
int i=5;myLabel.DataBindings.Add("Text", i, null);
int i=5;myLabel.DataBindings.Add("Text", i, null);
Proprietàcontrollo DataSource DataMember
se è null viene usatoToString()
Data binding: ApprofondimentiData binding: Approfondimenti
““Windows Forms Databinding”, Windows Forms Databinding”, Raffaele Rialdi, Raffaele Rialdi, workshop “Data Management”.workshop “Data Management”.
Denkiù!Denkiù!
LinksLinks
http://www.ugidotnet.org
http://forum.ugidotnet.org
http://mobile.ugidotnet.org
http://wiki.ugidotnet.org