To do this you have to update the data in the client. If you change the code of the button, the problem should be solved:
<xp:button id="SetViewScope" value="Toggle View Scope">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial" refreshId="PartialRefresh">
<xp:this.action>
<![CDATA[#{javascript:(viewScope.get("vsIsTrue")) ? viewScope.put("vsIsTrue",false) : viewScope.put("vsIsTrue",true)}]]>
</xp:this.action>
</xp:eventHandler>
</xp:button>
As you can see, the Event Handler updates now the button with the id PartialRefresh (the refreshMode is set to partial). When clicking Toggle View Scope, the CSJS DOM element is reloaded with the latest code. Next time you click the button and trigger a partial refresh, client sends the correct id to the server.
EDIT:
Another way is to do the same trick with a CSJS script block:
<xp:div id="refreshMe">
<xp:scriptBlock id="scriptBlockRefresh">
<xp:this.value>
<![CDATA[
var idPanelTrue = '#{id:panelTrue}';
var idPanelFalse = '#{id:panelFalse}';
var vsIsTrue = #{javascript:viewScope.get('vsIsTrue')};
XSP.allowSubmit();
var id = vsIsTrue?idPanelTrue:idPanelFalse;
XSP.partialRefreshPost(id,{});
]]>
</xp:this.value>
</xp:scriptBlock>
</xp:div>
Instead of refreshing the element, you are refreshing the CSJS sciptblock which then updates the correct XPage element. In this case, the Partial Refresh button has to look like this:
<xp:button value="Partial Refresh" id="PartialRefresh">
<xp:eventHandler event="onclick" submit="true" refreshMode="partial"
refreshId='refreshMe'>
</xp:eventHandler>
</xp:button>