You have a puzzler here. I've always had problems using global variables in the ToolValidator class. In addition, the .altered property doesn't always work as expected (at least for me). The trick seems to be: don't refresh a parameter if a proceeding one hasn't really changed. I think that is the basic problem you're having, and your globals weren't remembering any previous values correctly. Thus, every updateParameters check found a change, and the tool interface seemed as if it was locked up. It was actually being constantly refreshed to its previous state.
For my testing, I created a simple script tool with two input variables. The first used a multi-value string input from a value list filter "A;B;C;D" which gave me the check boxes. I used the multi-value "Any value" input to match your "SequenceTheMoveCodes" section. I did not use any globals in the ToolValidator. The operation seemed a bit quirky, but I could alter the order of the items, and delete some. This section would immediately refresh to new values when I deleted all values. Here's the code section from the ToolValidator:
def updateParameters(self):
if self.params[0].altered:
if self.params[0].values:
if self.params[1].values:
for v in self.params[0].values:
if v not in self.params[1].values:
self.params[1].values.append(v)
else:
self.params[1].values = self.params[0].values
return
As I mentioned, the operation seemed a bit quirky. I am also wondering if there is any value in adding the list of checkboxes when items can be deleted and reordered in the "sequence" section if it is working correctly. So I tested the following code. The first parameter was set to "workspace" so I could select a geodatabase. The second parameter was a "string" which could be populated with a dropdown list of domain names. The final parameter was the multi-value "any value" option to match your "sequence" section. These parameters seem to be the most important of what you are working with. Again, I did not use any global variables.
def updateParameters(self):
if self.params[0].altered:
if self.params[0].value:
domains = arcpy.da.ListDomains(self.params[0].value)
self.params[1].filter.list = sorted([d.name for d in domains if d.domainType == "CodedValue"])
if self.params[1].value not in self.params[1].filter.list:
self.params[1].value = self.params[1].filter.list[0]
if self.params[1].altered:
if self.params[1].value:
domains = arcpy.da.ListDomains(self.params[0].value)
for d in domains:
if d.name == self.params[1].value:
coded_values = d.codedValues
dVals = [val for val, desc in coded_values.items()]
if not self.params[2].values:
self.params[2].values = dVals
else:
for v in self.params[2].values:
if v not in dVals:
self.params[2].values = dVals
break
return
Basically, if a geodatabase and a domain name have been selected, the sequence section of the tool is populated with the codes from the first coded-value domain found. When a domain code is highlighted, the "x" button will remove it from the list. The up and down arrows should move the code in the list. If the domain name is changed, the script checks to see that all values in the sequence area are in the codes used by the newly selected domain. If a value exists that is not in the domain codes, it is assumed the domain name was changed, and the sequence section is refreshed. As noted in the code, I do not check that the workspace is an actual database. Also there is no error processing if the selected database does not have coded value domains.
Here's what my test tool interface looks like
Hope this helps.