There are tons of undo/redo code examples here on CodeProject. Or, you can also look at some old code I wrote (
RandomMonkeyWorks - Undo/Redo in C++[
^]). It isn't VB.Net, and you would have to modify it syntactically to your language, but that should provide a framework for applying in your case.
If you use my framework (and several other frameworks), you would have to add processing in the command handlers to populate the past actions stack, and write undo and redo code to handle the actual undoing and redoing of processing of the 2d array. I would simply create a list of previous values, and the x,y positions of those values, in the past actions stack. Then, after you have tied 'Ctrl-Z' and 'Ctrl-Y' (or whatever command signal) into 'undo' and redo, you use the 'undo' and 'redo' code to find the current value of that x,y position, store it, and place the next (or previous) value into that x,y position.
A simple example is given on the page I linked to.
Hope this helps.