Category Archive for vb.net

Risolviamo l’errore “DragDrop registration did not succeed” in .NET

Tempo fa mi è capitato di dover migrare alcune applicazioni dal Framework.NET 3.5 al 2.0, per esigenze di alcuni clienti. Su una in particolare è apparso l’errore “DragDrop registration did not succeed”. In effetti io avevo sviluppato qualche feature legata al drag ‘n’ drop, ma non riuscivo proprio a capire che cosa fosse fuori posto.

Ho fatto svariate ricerche, ma le informazioni su questo argomento specifico sono piuttosto scarse. Ad ogni modo, dopo alcuni sforzi ho trovato un breve ma efficace articolo di Frederick Chapleau, il quale esponeva chiaramente la risposta. Qual è? Ebbene, se abbiamo cambiato la versione del Framework di destinazione nelle opzioni di compilazione e se dovesse apparirci l’eccezione citata all’inizio, dobbiamo soltanto svuotare la cartella bin del progetto. Nel mio caso ha funzionato!

Come si può ottenere l’oggetto Assembly .NET corrente?

In ambiente .NET è possibile ricavare ed operare sui tipi, i metodi e le proprietà di qualunque assembly valido, grazie alla reflection. Probabilmente saprete già che è sufficiente importare il namespace System.Reflection per accedere a molte classi e funzionalità create a tale scopo.

Potrebbe sorgere, tuttavia, la domanda: come si può ottenere l’oggetto Assembly della propria applicazione? O meglio, dove posso trovare un riferimento all’assembly corrente, ossia quello che, a runtime, conterrà il codice che sto scrivendo? In sostanza, il codice deve recuperare informazioni su se stesso! Si può fare? La reflection consente anche questo?

La risposta è sì. Ecco il codice VB.NET di esempio:

Dim aAssembly As [Assembly] = System.Reflection.Assembly.GetExecutingAssembly
Dim sPath as String = System.Reflection.Assembly.GetExecutingAssembly.Location

La seconda riga mostra come recuperare il percorso fisico del file. Facile no? ;-)

Come richiamare più web service con la medesima classe proxy

Alcuni servers

Foto di ©G. D®oid ».

In ambiente .NET, quando vogliamo adoperare i web service solitamente aggiungiamo i web references. Una volta fatto ciò, scriviamo il codice per istanziarli e per chiamare i vari web methods. L’IDE di sviluppo genera automaticamente una classe proxy per ogni web reference aggiunto: noi usiamo sue le funzioni, che a loro volta invocheranno in modo appropriato il web service.

Tuttavia, potremmo avere n web service che implementano la stessa interfaccia e che forniscono dati differenti. Potremmo perfino non sapere a priori quanti web service avremo e dove saranno collocati! Ovviamente, in una situazione del genere non possiamo impostare dei web references a design time. Come si possono dunque invocare le funzioni di più web service (cioé quelle dell’interfaccia comune) usando una classe proxy “generica”?

Sembra qualcosa di molto complesso, ma in realtà, non è così: bastano pochi semplici passi. Sono i seguenti:

  • Aggiungi un web reference ad uno qualsiasi dei web services che implementano l’interfaccia cui abbiamo accennato all’inizio. Visual Studio creerà una classe che eredita da SoapHttpClientProtocol e la salverà in un file di nome Reference.vb;
  • Vai sul solution explorer e premi il pulsante per visualizzare tutti i files del progetto. Apri la cartella “Web References”, espandi l’elemento corrispondente al riferimento appena aggiunto (il nome di default è “localhost”);
  • A questo punto vedrai un file con estensione disco, uno con estensione wsdl ed un Reference.map. Espandi questo nodo e vedrai il file Reference.vb;
  • Crea una nuova classe, dandole il nome che desideri. Copia dentro tutto il contenuto della classe presente nel Reference.vb;
  • Sostituisci tutti i namespace in tutti gli attributi del proxy e delle sue funzioni: inserisci la stringa “http://tempuri.org/”, che è una sorta di valore di default. Ecco le parti da modificare (cercale nel testo e inserisci i valori in grassetto):

    [...]WebServiceBindingAttribute(Name:=”NomeDelNostroBinding”, [Namespace]:=“http://tempuri.org”)

    [...]

    SoapRpcMethodAttribute(“http://tempuri.org/NostroMetodo”, RequestNamespace:=“http://tempuri.org”, ResponseNamespace:=“http://tempuri.org”)

  • Testa il proxy.

Come sempre, per ulteriori spiegazioni, chiarimenti, domande e/o suggerimenti inerenti a questo breve articolo, scrivete un commento: sarà certamente letto e apprezzato! :-D

VB.NET: click destro per selezionare un elemento di una ListBox

Mouse alla Utrecht University

Foto di Bamshad.

Avete mai provato a mettere una ListBox in una form (di una windows form application), a riempirla e a selezionare un suo elemento con il tasto destro? Forse avete anche associato alla ListBox un menu contestuale. Ci si può aspettare che la classe ListBox aggiorni automaticamente la selezione su clic destro, ma non è così.

Cosa significa questo? Se voi selezionate il primo item tramite click sinistro, ad esempio, e poi fate clic destro sul terzo, vi apparirà il menu contestuale che avevate creato, ma la ListBox manterrà la selezione sul primo! Certamente il risultato ottenuto non è professionale né tantomeno funzionale.

Come si può implementare la selezione su clic destro, dunque? In realtà è molto semplice: bisogna gestire l’evento MouseDown del controllo, aggiornando il SelectedIndex in base alla posizione del mouse. Ecco il codice su cui potete basarvi:

Private Sub lsbList_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles lsbList.MouseDown
If e.Button = MouseButtons.Right Then
lsbList.SelectedIndex = lsbList.IndexFromPoint(New Point(e.X, e.Y))
End If
End Sub

Così facendo, con una veloce implementazione, potrete evitare molti comportamenti anomali nel programma che state creando e potreste anche fare bella figura!

Attenti al For Each!

Loop di colori sgargianti

Foto di Randy son of Robert.

Perché ho dato a quest’articolo un tema del genere? Il motivo è che qualche giorno fa ho avuto una brutta esperienza con i cicli For Each, dalla quale potrete trarre un’utile lezione.

Stavo cercando di costruirmi un array di Object, il quale doveva contenere delle stringhe valorizzate a String.Empty. Non chiedetemi quale sia la ragione per cui io lo stessi facendo, ma vi assicuro che era più che valida. Ecco il codice corrispondente:

Dim voEmpty(2) As Object
Dim i As Integer = 0
For Each o As Object in voEmpty
o = String.Empty
Next

Eseguendo questo pezzo di codice, ho notato che il vettore voEmpty continuava ad avere tutti gli elementi a Nothing. Perché? Non avevo pensato al fatto che il For Each fornisce un riferimento all’elemento iesimo della collezione: io stavo modificando la variabile d’appoggio, non gli elementi dell’array!

Qual è la lezione che possiamo trarre? I For Each non vanno usati per manipolare i dati di una collezione, ma al massimo per leggerla agevolmente, usando poche istruzioni. ;-)