Ruby, 258 247247 238 bytes
->c,t{c.tr (tr"#{$f='\'"+,-./<=>')+":;<=>?B-Z[]_b-z[]{'}"}:;B-Z_b-z",%W(-_}w[vzW]VZSsXJE>UIDCHTNMBRL"POYGK<QF:w[vzW]VZ/=?+SsXJE>UIDCHTNMBRL"POYGK<QF:{xje.uidchtnmbrl'poygk,qf;?+ #$f?}OoBCSFTDHUNEIMKY:QPRGLVWXJZ[]_bcsftdhuneimky;qprglvwxjz{}QPRGLVWXJZ_bcsftdhuneimky;qprglvwxjz #$f?}IiVMHRTGYUNEOLKP:QWSBFCDXJZ[]_vmhrtgyuneolkp;qwsbfcdxjz{}QWSBFCDXJZ_vmhrtgyuneolkp;qwsbfcdxjz)[t]} This is a function taking two arguments: the message to be swapped, and a value 0-2 representing the layout to be swapped to, where 0 corresponds to Dvorak, 1 to Colemak, and 2 to Workman.
Fundamentally, I don't think this is much different than the other answers. More readably, it looks like this:
def swap_layout(message, layout) keyboards = [DVORAK, COLEMAK, WORKMAN] # Omitted here for brevity return message.tr(QWERTY, keyboards[layout]) end Ruby's string#tr function takes two arguments: a string containing characters to be replaced, and a string containing their replacements. Helpfully, it allows you to specify ranges of characters using a-z syntax. The other key space-saving realization is that it's not necessary to include characters that are the same in all four layouts, which allowed me to get rid of all digits, the letter "A" in both upper- and lowercase, and a handful of special characters.
One other weird bit of syntax is the use of %W(). This creates an array of strings containing everything inside the parentheses, separated by whitespace. All linebreaks in the submission actually function as element separators. %W() also permits string interpolation (which is done with the #{} operator) - %w() would've been the same thing, but without string interpolation.
I'd also like to take a moment to blame Dvorak for messing with my plans for optimization through its insistence on being totally different than everyone else, all the time; a Qwerty/Colemak/Workman solution could have been so beautifully short...