You can get the UI working just by setting the grid.AllowDragSelectedCols = true. But this will not actually change the columns.
To manage this, you need to maintain a correspondence between the initial col positions and any moved col positions. You could do them in several ways, One would be to add an array of ints that you initialize 1 through the number of columns. Then when a column is moved, you move this elements of this int array. Also, anytime you access your external datasource, you use this index array to manage the proper corespondance. That''s the idea.
Now you could also add sort of a hidden row at the top of the grid that you use as this index array, and you initialize it to start as 1 to number of columns. The advantage is that the the grid itself will take care of moving these values.
Here is the modified VirtGrid tutorial that uses this technique. It adds (and hides) a row at the top of the grid, The SaveCellInfo and QueryCellInfo have been modified to use this row value as col index into the external data source. (Instead of adding a hidden row, if you are OK with storing values in the column headers, you could use the ColStyles.Tag to hold the original index for each column.)