Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[VB.NET] Datagridview e datatable - spostare righe

648 views
Skip to first unread message

Innuendo

unread,
Oct 20, 2010, 11:55:05 AM10/20/10
to
Ciao,
ho una form con una datagridview che viene popolata dall'utente pescando
dei dati da una listview.
La datagridview ha come datasource una datatable.

Adesso devo permettere all'utente di modificare l'ordine delle righe
tramite due bottoni "sposta su" e "sposta giu", ma non riesco a farlo.

Avevo giᅵ fatto una cosa simile funzionante ma con la datagridview non
collegata a un datasource, poi seguendo i consigli di Wodka40[google]
che mi consigliava di usare sempre un datasource ho risolto molti
problemi ma mi ᅵ spuntato questo che non riesco a risolvere :-(

Questo il codice (suppongo di voler spostare la riga 1)

' recupero la datatable usata come datasource per la datagridview
Dim dt As DataTable
dt = dg.DataSource

' faccio una copia della riga da spostare
Dim r As DataRow
r = dt.Rows(1)
' cancello la riga da spostare dalla datatable
dt.Rows.Remove(r)
dt.Rows.InsertAt(r, 1 + 1)

Il problema ᅵ che dopo l'istruzione dt.Rows.Remove(r) la riga r "non
esiste piᅵ", infatti il compilatore mi dice "Questa riga ᅵ stata rimossa
da una tabella e non contiene alcun dato."

Cosa sto sbagliando?

ciao
Mauro

Mauro Servienti [MVP]

unread,
Oct 20, 2010, 11:34:27 PM10/20/10
to
Ciao Innuendo,

You wrote on 20/10/2010 :
> ' faccio una copia della riga da spostare
> Dim r As DataRow
> r = dt.Rows(1)
> ' cancello la riga da spostare dalla datatable
> dt.Rows.Remove(r)
> dt.Rows.InsertAt(r, 1 + 1)
>

> Il problema è che dopo l'istruzione dt.Rows.Remove(r) la riga r "non esiste
> più", infatti il compilatore mi dice "Questa riga è stata rimossa da una

> tabella e non contiene alcun dato."

l'errore specifico è dovuto al fatto che dove dici che stai facendo la
copia della riga da spostare in realtà non copi un bel nulla, ma
semplicemente hai in mano un puntatore alla riga che poi cancelli, ergo
non serve a nulla.
Qui ti conviene approfondire i concetti di reference e value type.

> Cosa sto sbagliando?

In generale direi che non ha senso quello che stai cercando di fare, su
una tabella (DataTable o di database che sia) non ha senso il concetto
di ordine posizionale così come siamo abituati in una lista, perchè non
ha senso il concetto di indice by design, su una tabella ha senso il
concetto di ordine sulla base di un valore presente nella tabella, ergo
o hai una colonna "Sort" sulla base della quale poui ordinare i dati o
non c'è verso di fare quello che vuoi fare tu.

Quindi giusto sarebbe:

- avere una colonna che definisce l'ordinamento;
- mettere in binding la gurglia non direttamente con la tabella ma con
una DataView (vista sulla tabella) in cui espliciti le regole
sull'ordinamento;
- per cambiare ordinamento impostare i valori corretti nella colonna
Sort;
- eseguire il "refresh" della DataView;

.m

.m

--
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCTS
http://mvp.support.microsoft.com
blog @ http://milestone.topics.it
whynot [ at ] topics [ dot ] it


Innuendo

unread,
Oct 21, 2010, 5:32:31 AM10/21/10
to
Il 21/10/2010 5.34, Mauro Servienti [MVP] ha scritto:
> l'errore specifico è dovuto al fatto che dove dici che stai facendo la
> copia della riga da spostare in realtà non copi un bel nulla, ma
> semplicemente hai in mano un puntatore alla riga che poi cancelli, ergo
> non serve a nulla.
> Qui ti conviene approfondire i concetti di reference e value type.

Ciao, grazie per la dritta, devo trovare il modo di fare una copia della
riga per valore anzichè per riferimento ...

> In generale direi che non ha senso quello che stai cercando di fare, su
> una tabella (DataTable o di database che sia) non ha senso il concetto
> di ordine posizionale così come siamo abituati in una lista, perchè non
> ha senso il concetto di indice by design, su una tabella ha senso il
> concetto di ordine sulla base di un valore presente nella tabella, ergo
> o hai una colonna "Sort" sulla base della quale poui ordinare i dati o
> non c'è verso di fare quello che vuoi fare tu.

Ho capito cosa vuoi dire, ma nel mi applicativo la DatagridView
inizialmente è vuota, poi l'utente tramite interfaccia ci importa dentro
"righe" oppure "operazioni" (che sono semplicemente dei gruppi di righe).
A questo punto se la guarda per bene, decide di spostare su o giù
qualche riga, ne cancella alcune, ne aggiunge altre e così via.
Quando ritiene di aver finito preme salva e va tutto sul db, a quel
punto io valorizzo una colonna "numero riga" che mi serve per l'ordinamento.

Io non vorrei scrivere sul db ogni volta che l'utente inserisce una riga
o un gruppo di righe, possono essere anche centinaia le righe che
compongono una operazione ... preferisco che lavori "in ram" fino a
quando non è soddisfatto del risultato e solo allora salvo tutto sul db.

Il tuo suggerimento di utilizzare la catena

DataGridView -> DataView -> Db

è applicabile nel mio caso in cui la prima volta che arrivo nella
datagrid i dati non esistono ancora nel db?
Se vado in modifica di un ciclo esistente ok, ci posso provare, ma in
fase di creazione del ciclo come dovrei procedere?

grazie per l'aiuto, ciao
Mauro

Mauro Servienti [MVP]

unread,
Oct 22, 2010, 3:21:50 AM10/22/10
to
Ciao Innuendo,

You wrote on 21/10/2010 :
> Ho capito cosa vuoi dire, ma nel mi applicativo la DatagridView inizialmente

> ᅵ vuota, poi l'utente tramite interfaccia ci importa dentro "righe" oppure

> "operazioni" (che sono semplicemente dei gruppi di righe).

> A questo punto se la guarda per bene, decide di spostare su o giᅵ qualche
> riga, ne cancella alcune, ne aggiunge altre e cosᅵ via.


> Quando ritiene di aver finito preme salva e va tutto sul db, a quel punto io
> valorizzo una colonna "numero riga" che mi serve per l'ordinamento.
>
> Io non vorrei scrivere sul db ogni volta che l'utente inserisce una riga o un
> gruppo di righe, possono essere anche centinaia le righe che compongono una

> operazione ... preferisco che lavori "in ram" fino a quando non ᅵ soddisfatto

> del risultato e solo allora salvo tutto sul db.

nessuno ha detto che devi scrivere sul db, io non avevo neanche preso
in considerazione l'esistenza di un db :-P

> Il tuo suggerimento di utilizzare la catena
>
> DataGridView -> DataView -> Db
>

> ᅵ applicabile nel mio caso in cui la prima volta che arrivo nella datagrid i

> dati non esistono ancora nel db?

la catena ᅵ:

var myGrid = //a reference to the DataGridView

var dataTable = new MyDataTable();
var view = dataTable.DefaultView;
view.Sort = "SortOrder asc";

myGrid.DataSource = view;

> Se vado in modifica di un ciclo esistente ok, ci posso provare, ma in fase di
> creazione del ciclo come dovrei procedere?

la griglia ha sempre una sorgente dati, nella peggiore delle ipotesi ᅵ
vuota.

> grazie per l'aiuto, ciao
> Mauro

.m

Innuendo

unread,
Oct 22, 2010, 8:23:55 AM10/22/10
to
Il 21/10/2010 05:34, Mauro Servienti [MVP] ha scritto:
> semplicemente hai in mano un puntatore alla riga che poi cancelli, ergo
> non serve a nulla.
> Qui ti conviene approfondire i concetti di reference e value type.
Mi sono documentato per bene sui tipi reference e sui tipi value, la
differenza mi ᅵ molto chiara.

Quello che non riesco a capire allora ᅵ come mai questo codice funziona:

Private Sub btnUp_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnUp.Click
'controllo di non essere alla prima riga della datagridview
If RigaSelezionata > 0 Then
'creo una variabile di appoggio di tipo RIGA DI DATAGRIDVIEW
Dim R As DataGridViewRow
'copio per intero la riga da spostare
R = DataGridView1.Rows(RigaSelezionata)
'tolgo la riga vecchia
DataGridView1.Rows.Remove(R)
'inserisco la copia della riga SOPRA quella che devo togliere
DataGridView1.Rows.Insert(RigaSelezionata - 1, R)
'mantengo la selezione sulla riga spostata
DataGridView1.Rows(RigaSelezionata - 1).Selected = True
'ed aggiorno di conseguenza la variabile che indica la selezione
RigaSelezionata -= 1
'ridisegno la datagridview
DataGridView1.Refresh()
End If
End Sub


mentre il mio no. Anche qua R ᅵ la copia di un puntatore alla riga
selezionata che subito doppo rimuovo ...

Il codice completo dell'esempio che ti ho fatto lo trovi qua:
http://www.dotnethell.it/forum/ShowCode.aspx?MessageID=103565&Frag=0

grazie, ciao
Mauro

Mauro Servienti [MVP]

unread,
Oct 24, 2010, 4:56:29 AM10/24/10
to
Ciao Innuendo,

You wrote on 22/10/2010 :
> mentre il mio no. Anche qua R ᅵ la copia di un puntatore alla riga
> selezionata che subito doppo rimuovo ...

forse perchᅵ sono completamente diversi?

Il tuo codice ragiona su una DataTable, l'esempio che riporti ragiona
su una DataGridView.

Innuendo

unread,
Oct 24, 2010, 8:36:59 AM10/24/10
to
Il 24/10/2010 10.56, Mauro Servienti [MVP] ha scritto:
> forse perchᅵ sono completamente diversi?
>
> Il tuo codice ragiona su una DataTable, l'esempio che riporti ragiona su
> una DataGridView.

Si, ma non si tratta in entrambi i casi di oggetti "riga" e quindi non
sono tutti e due tipi reference? E' questo che non riesco a capire.

ciao e grazie
Mauro

Mauro Servienti [MVP]

unread,
Oct 24, 2010, 9:55:30 AM10/24/10
to
Ciao Innuendo,

You wrote on 24/10/2010 :
> Si, ma non si tratta in entrambi i casi di oggetti "riga" e quindi non sono
> tutti e due tipi reference? E' questo che non riesco a capire.

si certo, la differenza sta nel funzionamento del metodo "Remove".

Facciamo una prima considerazione, in entrambi i casi dire che si sta
facendo "una copia per intero della riga" ᅵ un grave errore perchᅵ si
sta creando semplicemente un nuovo puntatore (reference) che punta alla
posizione in memoria dove si trovano le informazioni relative alla riga
in oggetto.

La DataGridView quando chiami remove semplicemente rimuove dalla sua
collection di righe la riche in oggetto e siccome tu hai in mano una
reference a quella riga la puoi mettere in un altro posto e il tutto
funziona, la DataTable quando chiami remove non rimuove un bel nulla
semplicemente marca la riga come "deleted", ᅵ il funzionamento della
DataTable, quindi quando cerchi di aggiungere una riga deleted in un
posto diverso giustamente lei si incazza.

Innuendo

unread,
Oct 24, 2010, 3:26:06 PM10/24/10
to
Il 24/10/2010 15.55, Mauro Servienti [MVP] ha scritto:
> Facciamo una prima considerazione, in entrambi i casi dire che si sta
> facendo "una copia per intero della riga" ᅵ un grave errore perchᅵ si
> sta creando semplicemente un nuovo puntatore (reference) che punta alla
> posizione in memoria dove si trovano le informazioni relative alla riga
> in oggetto.
Ok, fino qua ve bene !


> La DataGridView quando chiami remove semplicemente rimuove dalla sua
> collection di righe la riche in oggetto e siccome tu hai in mano una
> reference a quella riga la puoi mettere in un altro posto e il tutto
> funziona, la DataTable quando chiami remove non rimuove un bel nulla
> semplicemente marca la riga come "deleted", ᅵ il funzionamento della
> DataTable, quindi quando cerchi di aggiungere una riga deleted in un
> posto diverso giustamente lei si incazza.

Ah, ok, adesso ho capito, grazie per l'ottima spiegazione !!!

Adesso proseguo con i miei tentativi per implementare il funzionamento
tramite la DataView ... finora non ci sono riuscito, mi si incasina
tutto quando la currentRow non ᅵ piᅵ nell'insieme delle SelectedCells o
qualcosa del genere, non ho ancora capito.

ciao
Mauro

Innuendo

unread,
Oct 26, 2010, 4:00:28 AM10/26/10
to
Il 22/10/2010 09:21, Mauro Servienti [MVP] ha scritto:
> la catena ᅵ:
>
> var myGrid = //a reference to the DataGridView
>
> var dataTable = new MyDataTable();
> var view = dataTable.DefaultView;
> view.Sort = "SortOrder asc";
>
> myGrid.DataSource = view;

Ciao,
chiedo ancora un aiuto. Non riesco proprio a capire come faccio a
spostare su un gruppo di celle.

Sto provando in questo modo:

0. ho aggiunto alla datagrid e alla datatable la colonna peso e assegno
un peso crescente alle righe, ho creato la vista e ho ordinato la datagrid
1. leggo l'elenco delle SelectedRows della datagrid e metto gli indici
di riga in una lista
2. per ogni elemento della lista diminuisco il suo peso e aumento il
peso della riga con indice precedente
3. riordino la vista in base al peso

Ma non mi funziona, non riesco nemmeno a capire il perchᅵ :-(

Se seleziono un unica riga funziona, poi modifico la selezione per
spostare un'altra riga e mi legge il peso sbagliato, ovvero il peso che
aveva la riga prima di fare il primo spostamento.

E' come se una volta che ho modificato i pesi questi non venissero
memorizzati nella datatable ...

For Each i In lista
dt.Rows(i).Item("peso") = (dt.Rows(i).Item("peso") - 10)
dt.Rows(i - 1).Item("peso") = (dt.Rows(i - 1).Item("peso") + 10)
v.Sort = "peso"
'dg.DataSource = dt
Next

Ho fatto mille prove, ma non riesco a capire cosa sbaglio, qualcuno ᅵ in
grado di indirizzarmi ?

ciao, grazie
Mauro

Mauro Servienti [MVP]

unread,
Oct 26, 2010, 11:41:45 PM10/26/10
to
Ciao Innuendo,

You wrote on 26/10/2010 :
> For Each i In lista
> dt.Rows(i).Item("peso") = (dt.Rows(i).Item("peso") - 10)
> dt.Rows(i - 1).Item("peso") = (dt.Rows(i - 1).Item("peso") + 10)
> v.Sort = "peso"
> 'dg.DataSource = dt
> Next
>
> Ho fatto mille prove, ma non riesco a capire cosa sbaglio, qualcuno ᅵ in
> grado di indirizzarmi ?

Direi che non ᅵ cosᅵ facile :-), hai bisogno di piᅵ informazioni e stai
dando per scontate un paio di cose che scontate non sono affatto.

Per spostare degli elementi in una lista hai bisogno di:
- direzione dello spostamento;
- reference (o indice) degli elementi da spostare;

Se gli elementi che devi spostare sono da spostare in "blocco", quindi
devi supportare la selezione multipla la cosa si complica perchᅵ devi
anche capire se gli elementi sono contigui e trattare quelli contigui
com e un blocco unico.

Hai poi la casistica di selezione mista: seleziono i primi 3 insieme
poi con il "ctrl" aggiungo alla selezione anche il 5, e voglio spostare
verso il basso... i primi 3 andranno in blocco dopo il 4 mentre il 5
andrᅵ dopo il sesto... sempre che un sesto ci sia, perchᅵ se il quinto
fosse l'ultimo non devi spostarlo...

Insomma quel ciclo foreach non puᅵ proprio funzionare.

Ma non ᅵ finita, stai partendo dal pressupposto che gli indici nella
griglia siano gli stessi nella DataTable, ma la girglia rispecchia
l'ordine della DataView quindi ᅵ pressochᅵ impossibile questa cosa se
non forse al primo DataBinding, devi quindi risalire alla "righe"
selezionate nella DataTable partendo si da quelle selezionate nella
griglia ma andando a cercare gli item in binding e non passando per
gl'indici.

Mi rendo conto che ti ho complicato la vita, ma ᅵ il bello del nostro
lavoro ed ᅵ l'unico motivo per cui lo faccio ancora :-P

Innuendo

unread,
Oct 27, 2010, 3:06:24 AM10/27/10
to
Il 27/10/2010 05:41, Mauro Servienti [MVP] ha scritto:
> Per spostare degli elementi in una lista hai bisogno di:
> - direzione dello spostamento;
> - reference (o indice) degli elementi da spostare;

E questi dati li ho tutti, io per brevitᅵ ho postato solo una parte del
codice di "sposta su"

> Hai poi la casistica di selezione mista: seleziono i primi 3 insieme poi
> con il "ctrl" aggiungo alla selezione anche il 5, e voglio spostare
> verso il basso... i primi 3 andranno in blocco dopo il 4 mentre il 5
> andrᅵ dopo il sesto... sempre che un sesto ci sia, perchᅵ se il quinto
> fosse l'ultimo non devi spostarlo...
>
> Insomma quel ciclo foreach non puᅵ proprio funzionare.

Ma prima mi funzionava :-(

Prima usavo una datagridview popolata una riga alla volta scorrendo i
risultati di una query tramite un datareader (oppure selezionando gli
elementi da una listbox nel caso di avvio da datagridview vuota) e tutto
funzionava a meraviglia, compresa la selezione multipla con elementi
contigui e non.
Il codice che funzionava ᅵ il seguente:

Private Sub btnSpostaSu_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnSpostaSu.Click
Dim lista As New ArrayList
' Leggo gli indici delle righe selezionate e li metto in un array
For Each row In dgCicloLavorazione.SelectedRows
lista.Add(row.Index)
Next
lista.Sort()

' Per ogni elemento della lista sposto la riga in su di uno


For Each i In lista

rigaSelezionata = i
If rigaSelezionata > 0 Then


'creo una variabile di appoggio di tipo RIGA DI DATAGRIDVIEW
Dim R As DataGridViewRow
'copio per intero la riga da spostare

R = dgCicloLavorazione.Rows(rigaSelezionata)
'tolgo la riga vecchia
dgCicloLavorazione.Rows.Remove(R)


'inserisco la copia della riga SOPRA quella che devo togliere

dgCicloLavorazione.Rows.Insert(rigaSelezionata - 1, R)


'mantengo la selezione sulla riga spostata

dgCicloLavorazione.Rows(rigaSelezionata - 1).Selected = True
'rimuovo la selezione dalla riga precedente
dgCicloLavorazione.Rows(rigaSelezionata + 1).Selected = False


'ed aggiorno di conseguenza la variabile che indica la selezione

If (lista.Count() > 1) Then

Else
dgCicloLavorazione.CurrentCell = dgCicloLavorazione.Item(0,
rigaSelezionata - 1)
End If

End If
Next

dgCicloLavorazione.Refresh()
Me.ricalcola_righe()
End Sub

Poi, seguendo vari consigli ricevuti su questo NG per risolvere altri
problemi ho modificato il modo di caricare i dati nella datagridview e
adesso con la query popolo una datatable che poi utilizzo come
datasource della datagridview e quindi il codice di sopra non funziona
piᅵ :-(

E lo stesso metodo applicato alla datatable anzichᅵ alla datagridview
non funziona perchᅵ come mi hai spiegato tu il metodo remove di
datagridview e di datatable ᅵ molto diverso nel funzionamento.

> Ma non ᅵ finita, stai partendo dal pressupposto che gli indici nella
> griglia siano gli stessi nella DataTable, ma la girglia rispecchia
> l'ordine della DataView quindi ᅵ pressochᅵ impossibile questa cosa se
> non forse al primo DataBinding, devi quindi risalire alla "righe"
> selezionate nella DataTable partendo si da quelle selezionate nella
> griglia ma andando a cercare gli item in binding e non passando per
> gl'indici.

questo non mi ᅵ molto chiaro .... ma penso che tu abbia centrato il
punto, infatti alla prima iterazione mi funziona, se poi ripremo il
pulsante "sposta su" senza aver riselezionato gli elementi esplode tutto :-)

Per il problema dell'ordinamento ho provato a risolvere aggiungendo una
colonna "peso" che viene valorizzata quando popolo la datagridview un
elemento alla volta oppure quando leggo i dati dal db man mano che li
leggo assegno un peso crescente.

Poi pensavo che quando l'utente fa "sposta su" modifico il valore della
colonna peso di quella riga e di quella superiore/inferiore e riordino
il tutto con view.sort ma anche in questo modo mi sa che mi perdo
qualche pezzo per strada tra datagridview - datasource - datatable -
selezione ecc ecc

ciao
Mauro

Wodka40[Google]

unread,
Oct 27, 2010, 5:57:53 AM10/27/10
to
On 27 Ott, 09:06, Innuendo <a...@b.c> wrote:
> Il 27/10/2010 05:41, Mauro Servienti [MVP] ha scritto:
zacchete

Stamani mi avanzava tempo....e poi sono in preparazione mistica, a
base di camomilla dell'Himalaya e Joga Uzbeko, in vista delle 5 ore di
corso "base" sull'utilizzo di stasera! OMMMMMMMMM!
Quindi mi andava di programmare qualcosa

NON ho utilizzato i tasti su e giu...ma il mouse!...va perfezionato e
limato il codice ed infarcito di try catch...ma l'idea funziona!

Accade questo:
L'utente clicca con il tasto destro sulla riga che vuole
spostare ....e tenendo premuto muove il mouse....appare una icona
(drag & drop)....avendolo spostato può anche rilasciare il mouse la
griglia ha capito che vuoi spostare la riga....adesso trovi la
destinazione (usando scroll o quello che vuoi) e CONFERMI usando il
tasto sinistro (faccio più fatica a spiegarlo che a farlo!)
Fatto...i valori vengono swappati....siccome mi ricordavo che il
riferimento ordine NON VUOI swapparlo....quello rimane li!

Funziona!
Allora VS2010 un form una datagridview...sopra una label (per far
vedere al tuo utente cosa sta facendo) e un button per mostrare a
Innuendo che la tabella è davvero aggiornata!

AVVERTENZE:
la form si chiama gridStart...
la label lblStatus
il button btnTest
LA GRIGLIA HA NELLE PROPRIETA': ALLOWDROP TRUE

Saluti!

Codice:

Public Class GridStart
Dim Tabella As New System.Data.DataTable
Dim DumRiga As DataRow
Private FLAG_SPOSTA As Boolean = False
Dim riga1 As DataGridViewRow
Dim riga2 As DataGridViewRow

Private Sub GridStart_Load(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles MyBase.Load
myGrid.Anchor = AnchorStyles.Top Or AnchorStyles.Left Or
AnchorStyles.Right
CaricaDati()
End Sub

Private Sub CaricaDati()
Tabella.Columns.Add("RifOrdine",
Type.GetType("System.String"))
Tabella.Columns.Add("Descrizione",
Type.GetType("System.String"))
Tabella.Columns.Add("Qta", Type.GetType("System.Int32"))
Tabella.Columns.Add("Prezzo", Type.GetType("System.Decimal"))
'Dati
For n As Integer = 0 To 20

Dim record As DataRow = Tabella.NewRow()
record(0) = n
record(1) = ("Prodotto prova cod." + n.ToString)
record(2) = Int((30 - 10 + 1) * Rnd() + 10) 'numero fra 10
e 30
record(3) = CDec(((12.5 - 3.0 + 1) * Rnd() + 3.0)) 'numero
fra 3.0 e 12.5
'aggiungi
Tabella.Rows.Add(record)

Next
' visualizza nella griglia
myGrid.AutoGenerateColumns = True

myGrid.DataSource = Tabella
myGrid.Columns(1).Width = 328
End Sub

Private Sub myGrid_DragDrop(ByVal sender As Object, ByVal e As
System.Windows.Forms.DragEventArgs) Handles myGrid.DragDrop
Try
Dim t As DataGridView.HitTestInfo
t = myGrid.HitTest(e.X, e.Y)
e.Effect = DragDropEffects.None
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub

Private Sub myGrid_DragEnter(ByVal sender As Object, ByVal e As
System.Windows.Forms.DragEventArgs) Handles myGrid.DragEnter
'qui ha capito che voglio modificare
FLAG_SPOSTA = True
lblStatus.Text = "SPOSTAMENTO"
End Sub

Private Sub myGrid_DragLeave(ByVal sender As Object, ByVal e As
System.EventArgs) Handles myGrid.DragLeave
' MsgBox("Hai lasciato")
Dim t As New Point
t.X = MousePosition.X
t.Y = MousePosition.Y
Dim trisp As DataGridView.HitTestInfo
trisp = myGrid.HitTest(t.X, t.Y)
lblStatus.Text = "lasciato"

End Sub

Private Sub myGrid_DragOver(ByVal sender As Object, ByVal e As
System.Windows.Forms.DragEventArgs) Handles myGrid.DragOver
e.Effect = DragDropEffects.Move

End Sub

Private Sub myGrid_MouseDown(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles myGrid.MouseDown
Dim Index As Integer
If e.Button = MouseButtons.Right Then
Index = myGrid.HitTest(e.X, e.Y).RowIndex
If Index > -1 Then 'Pass the Index as "Data"
argument of the DoDragDrop Function
myGrid.DoDragDrop(Index, DragDropEffects.Move)
'memorizza la partenza
riga1 = myGrid.Rows(Index)
End If
End If
End Sub

Private Sub myGrid_MouseUp(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles myGrid.MouseUp
If FLAG_SPOSTA = True Then
FLAG_SPOSTA = False
Dim index As Integer
index = myGrid.HitTest(e.X, e.Y).RowIndex
'eseguo lo swap
'casomai "mirato"
riga2 = myGrid.Rows(index)
'******************************
'ho bisogno di una terza riga clone per lo swap
Dim rigaswap As DataGridViewRow
rigaswap = riga2.Clone
'NON FUNZIONA: troppo bello...non fà un deep copy....i
valori non li ricopia!
' a manina cari miei...o derivando
' sono pochi campi...lo faccio a manina!
rigaswap.Cells(1).Value = riga2.Cells(1).Value
rigaswap.Cells(2).Value = riga2.Cells(2).Value
rigaswap.Cells(3).Value = riga2.Cells(3).Value
'....faticaccia finita!
'******************************
'il contenuto di riga1 sovrascrive riga 2 ...solo nei
campi 1 2 3
riga2.Cells(1).Value = riga1.Cells(1).Value
riga2.Cells(2).Value = riga1.Cells(2).Value
riga2.Cells(3).Value = riga1.Cells(3).Value
'adesso tocca a riga 1
riga1.Cells(1).Value = rigaswap.Cells(1).Value
riga1.Cells(2).Value = rigaswap.Cells(2).Value
riga1.Cells(3).Value = rigaswap.Cells(3).Value
' butta via cella swap
rigaswap.Dispose()

lblStatus.Text = "Normale"
End If
End Sub

Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnTest.Click
For Each Triga As DataRow In Tabella.Rows
Console.WriteLine("Rif Ordine:{0} Prodotto:{1} Qta:{2}
Prezzo:{3}", Triga.Item(0).ToString, Triga.Item(1).ToString,
Triga.Item(2).ToString, Triga.Item(3).ToString)
Next
Stop ' per guardare cosa è accaduto nella tabella!
End Sub
End Class

Wodka40[Google]

unread,
Oct 27, 2010, 6:02:16 AM10/27/10
to
On 27 Ott, 11:57, "Wodka40[Google]" <virgultoamor...@latinmail.com>
wrote:

> On 27 Ott, 09:06, Innuendo <a...@b.c> wrote:> Il 27/10/2010 05:41, Mauro Servienti [MVP] ha scritto:
>
> zacchete
>
> Stamani mi avanzava tempo....e poi sono in preparazione mistica, a
> base di camomilla dell'Himalaya e Joga Uzbeko, in vista delle 5 ore di
> corso "base" sull'utilizzo di stasera! OMMMMMMMMM!
zac

Non mi riesce nemmeno scriverlo......
utilizzo del pc!
non di qualche strana sostanza....magari!(almeno non mi facevo 2 palle
così con gente che clicca dappertutto a vanvera!)

Innuendo

unread,
Oct 27, 2010, 8:43:05 AM10/27/10
to
Il 27/10/2010 11:57, Wodka40[Google] ha scritto:
[ ... ]

> ' a manina cari miei...o derivando
> ' sono pochi campi...lo faccio a manina!

In sostanza copi i valori contenuti nelle celle della riga di partenza
nelle celle della riga di destinazione usando una riga temporanea ....
mi sembrava un po' una brutalit�, ma visto che di copiare la riga intera
in blocco proprio non c'e' verso ... TI SEGUO :-) !!!

Provo ad adattare il tuo codice al mio progetto, intanto grazie per
l'ennesima dritta !

ciao
Mauro

Wodka40[Google]

unread,
Oct 28, 2010, 4:33:06 AM10/28/10
to
On 27 Ott, 14:43, Innuendo <a...@b.c> wrote:
> Il 27/10/2010 11:57, Wodka40[Google] ha scritto:
> [ ... ]
>
> >              ' a manina cari miei...o derivando
> >              ' sono pochi campi...lo faccio a manina!
>
> In sostanza copi i valori contenuti nelle celle della riga di partenza
> nelle celle della riga di destinazione usando una riga temporanea ....
> mi sembrava un po' una brutalità, ma visto che di copiare la riga intera
zac
....senza fare il filosofo: la vita E' brutalità!...infatti ci siamo
inventati il Paradiso e la Religione!

Innuendo

unread,
Oct 28, 2010, 6:09:03 AM10/28/10
to
Il 28/10/2010 10:33, Wodka40[Google] ha scritto:
> .....senza fare il filosofo: la vita E' brutalit�!...infatti ci siamo

> inventati il Paradiso e la Religione!

:-)

Sono riuscito a fare tutto quello che volevo in un progettino ad hoc, ma
quando lo riporto nel progetto dove mi serve effettivamente ottengo un
eccezzione in datagridview che mi dice:

"la colonna id_cdl � in sola lettura"

ma io non ho mai messo quella colonna in sola lettura !!! :-( :-( :-(

Perch� mi fa questo? E sopratutto, come posso evitarlo?

Ho provato a fare

dgCicloLavorazione.Columns("id_cdl").ReadOnly = False

ma non gli va bene lo stesso, ottengo l'errore "Per una colonna
DataGridView associata a un campo in sola lettura ReadOnly deve essere
impostato su True."

ciao e grazie
Mauro

Wodka40[Google]

unread,
Oct 28, 2010, 6:27:52 AM10/28/10
to
On 28 Ott, 12:09, Innuendo <a...@b.c> wrote:
> Il 28/10/2010 10:33, Wodka40[Google] ha scritto:
IMHO!

Connetto il db
Popolo la datatable
STACCO TUTTO

lavoro....

Connetto di nuovo il db
Aggiorno!

Per me...ma la palla di cristallo l'ho rotta...hai qualche relazione
che impedisce l'aggiornamento! Sai le query son brutte bestie!
Tu se vuoi fare lo spippolamento che mi dicevi
DEVI...DEVI...
usare la griglia non come griglia ma come array di celle...tu vuoi
ROMPERE l'unità del record ...e quindi devi essere libero da vincoli!
Cosa che probabilmente non hai fatto nella tua applicazione!
Vuoi fare il "sommo spippolamento carpiato come se fosee antani alla
blinda supercazzola": cambiare gli ID che sempre si blindano con una
primary key!...sempre se sei al cambio ordine di qualche post fà!

...io sono sempre perplesso è son sempre dell'idea che alla fine
l'uTonto che userà il tuo programma prima o poi sarà proprio
Tonto....e spedirai un set di finissimi sottobicchieri ricamati della
ValTellina a chi ha comprato la bambola gonfiabile "gina la
porcellina" ...ma tant'è!!!
:)

Innuendo

unread,
Oct 28, 2010, 6:48:55 AM10/28/10
to
Il 28/10/2010 12:27, Wodka40[Google] ha scritto:
> Connetto il db
> Popolo la datatable
> STACCO TUTTO
>
> lavoro....
>
> Connetto di nuovo il db
> Aggiorno!

Ma io faccio esattamente cos�.

' Creo la Datasource di appoggio
Dim dt As New DataTable
dt.Columns.Add("id_cdl", Type.GetType("System.Int32"))
dt.Columns.Add("id_rev_ciclo", Type.GetType("System.Int32"))
dt.Columns.Add("id_operazione", Type.GetType("System.Int32"))
dt.Columns.Add("numero_riga", Type.GetType("System.Int32"))
dt.Columns.Add("nome", Type.GetType("System.String"))
dt.Columns.Add("fase", Type.GetType("System.String"))
dt.Columns.Add("sottofase", Type.GetType("System.String"))
dt.Columns.Add("tipo", Type.GetType("System.String"))
' La collego alla datagridview
dgCicloLavorazione.DataSource = dt

Poi se serve popolo la datagridview leggendo i dati dal database usando
la seguente funzione:

Public Sub query_to_datagrid(ByRef dg As DataGridView, ByVal sql As
String, Optional ByVal echo As Boolean = False)
' Svuoto la datagrid
dg.DataSource = Nothing
dg.Rows.Clear()
dg.Columns.Clear()

' Faccio la query
Using conn As New OdbcConnection(Me.dsn)
Dim command As New OdbcCommand(sql, conn)

Try
conn.Open()
Using tmpTable As New DataTable
Dim dr As OdbcDataReader = command.ExecuteReader
tmpTable.Load(dr)
dr.Close()

' Aggiungo le righe alla datatable
dg.AutoGenerateColumns = True
dg.DataSource = tmpTable
End Using
Catch ex As Exception
MsgBox("Impossibile eseguire la query" & vbCrLf & ex.Message)
End Try
End Using
End Sub

e se faccio la controprova con:

MsgBox("Prima: " & dgCicloLavorazione.Columns("id_cdl").ReadOnly)

db.query_to_datagrid(dgCicloLavorazione, "select * from v_cdl where
id_rev_ciclo=" & id_rev_ciclo)

MsgBox("Dopo: " & dgCicloLavorazione.Columns("id_cdl").ReadOnly)

In pratica prima di chiamare la funzione query_to_datagrid la colonna
NON � in readonly, mentre dopo lo �.

Io penso che il problema sia nel "cambio" di datasource ma non capisco
perche'

ciao
Mauro


p.s.
come'e' andata ieri sera il corso?

Wodka40[Google]

unread,
Oct 28, 2010, 1:47:28 PM10/28/10
to
On 28 Ott, 12:48, Innuendo <a...@b.c> wrote:
> Il 28/10/2010 12:27, Wodka40[Google] ha scritto:
zac

> In pratica prima di chiamare la funzione query_to_datagrid la colonna
> NON è in readonly, mentre dopo lo è.
>
MAH!
Ripeto ...la palla di cristallo non ce l'ho!
Ipotizzo:Hai delle relazioni? Controlla che NON ci siano sulla
tabella...ci sono oggetti appositi!
Controlla le primary key...o indici...o quant'altro...imho NON hai
problemi con la griglia ma con la tabella!

Hai problemi con la griglia...questo si...se hai del codice EXTRA
rispetto a quello che ci siamo scambiati...
Stai copiando una riga?...la riga è usata da altro? La colonna è
bloccata perchè coinvolta in un aggiornamento senza fine?...


> Io penso che il problema sia nel "cambio" di datasource ma non capisco

Io invece penso un altra cosa rileggendo....
Fatti una query che riporta tutto quello che vuoi...e poi fai creare
la tabella al datareader! Perchè crei una datatable prima? A che
serve? A buttar via cicli macchina?


> ciao
> Mauro
>
> p.s.
> come'e' andata ieri sera il corso?

Una tragedia....quasi 5 ore con gente che clicca dappertutto (anche
sui muri)...tranne che sull'icona "start"!!!

p.s.
Domani c'ho quasi la mattina libera....guardo se ti butto giu un
esempio (con Access) dell'aggancio tabella!

Innuendo

unread,
Oct 28, 2010, 3:56:34 PM10/28/10
to
Il 28/10/2010 19.47, Wodka40[Google] ha scritto:
> Hai problemi con la griglia...questo si...se hai del codice EXTRA
> rispetto a quello che ci siamo scambiati...
> Stai copiando una riga?...la riga � usata da altro? La colonna �
> bloccata perch� coinvolta in un aggiornamento senza fine?...
No no, il codice "incriminato" � tutto li, se tolgo il dg.DataSource =
Nothing funziona tutto come devo.

Escluderei problemi di colonne/vincoli sulla tabella, ho fatto anche una
prova con una tabella di test creata appositamente con e senza primary key.

In pratica se:
1. creo una datatable
2. la setto come datasource della datagrid
3. entro nella funzione di libreria
4. rimuovo la datasource della datagrid
5. faccio la query mettendo il risultato in una tmp_datatable
6. la setto come datasource della datagrid

NON posso fare le modifiche perche' la prima colonna della datagridview
� readonly.

Se invece
1. creo una datatable
2. la setto come datasource della datagrid
3. entro nella funzione di libreria
4. recupero la datasource della datagrid
5. faccio la query mettendo il risultato nella datatable recuperata al
punto 4

funziona tutto alla perfezione.
Sarei curioso di capire perche' il mettere e togliere un datasource a
una datagridview provoca il blocco in readonly della prima colonna.

> Io invece penso un altra cosa rileggendo....
> Fatti una query che riporta tutto quello che vuoi...e poi fai creare

> la tabella al datareader! Perch� crei una datatable prima? A che


> serve? A buttar via cicli macchina?

Uhm ... che domanda difficile :-) ... ho fatto cos� seguendo il tuo
esempio, prima se ricordi facevo tutto a manina creando una colonna e
una riga alla volta man mano che scorrevo il datareader.


Tu mi avevi consigliato di usare una cosa del tipo:

Dim miaTab As New DataTable(NomeTable)
Using DR As Npgsql.NpgsqlDataReader =
comando.ExecuteReader(CommandBehavior.KeyInfo)
miaTab.Load(DR)
DR.Close()
End Using

non � la stessa cosa che ho fatto io?

Io per domani provo a preparare i due esempi di modo che chi in futuro
seguir� questo thread avr� una risposta definitiva.
Un miniprogetto per spostare in alto e in basso gruppi di righe in una
datagrid l'ho quasi pronto.
Adesso vedo di fare anche questo del datasource

ciao e grazie per l'aiuto
Mauro

0 new messages