Index: src/sas/qtgui/Perspectives/Fitting/AssociatedComboBox.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/AssociatedComboBox.py	(revision 04f775db13543cbc91b64834af6068a163b77f8b)
+++ src/sas/qtgui/Perspectives/Fitting/AssociatedComboBox.py	(revision 04f775db13543cbc91b64834af6068a163b77f8b)
@@ -0,0 +1,38 @@
+from PyQt5 import QtGui, QtWidgets
+
+
+class AssociatedComboBox(QtWidgets.QComboBox):
+    """Just a regular combo box, but associated with a particular QStandardItem so that it can be used to display and
+    select an item's current text and a restricted list of other possible text.
+
+    When the combo box's current text is changed, the change is immediately reflected in the associated item; either
+    the text itself is set as the item's data, or the current index is used; see constructor."""
+    item = None  # type: QtGui.QStandardItem
+
+    def __init__(self, item, idx_as_value=False, parent=None):
+        # type: (QtGui.QStandardItem, bool, QtWidgets.QWidget) -> None
+        """
+        Initialize widget. idx_as_value indicates whether to use the combo box's current index (otherwise, current text)
+        as the associated item's new data.
+        """
+        super(AssociatedComboBox, self).__init__(parent)
+        self.item = item
+
+        if idx_as_value:
+            self.currentIndexChanged[int].connect(self._onIndexChanged)
+        else:
+            self.currentTextChanged.connect(self._onTextChanged)
+
+    def _onTextChanged(self, text):
+        # type: (str) -> None
+        """
+        Callback for combo box's currentTextChanged. Set associated item's data to the new text.
+        """
+        self.item.setText(text)
+
+    def _onIndexChanged(self, idx):
+        # type: (int) -> None
+        """
+        Callback for combo box's currentIndexChanged. Set associated item's data to the new index.
+        """
+        self.item.setText(str(idx))
Index: src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py	(revision b764ae5882f084a8b74c7cf664276c13fb07c29e)
+++ src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py	(revision 04f775db13543cbc91b64834af6068a163b77f8b)
@@ -8,4 +8,6 @@
 from sas.qtgui.Plotting.PlotterData import Data1D
 from sas.qtgui.Plotting.PlotterData import Data2D
+
+from sas.qtgui.Perspectives.Fitting.AssociatedComboBox import AssociatedComboBox
 
 model_header_captions = ['Parameter', 'Value', 'Min', 'Max', 'Units']
@@ -61,5 +63,33 @@
     return (param_name, param_length)
 
-def addParametersToModel(parameters, kernel_module, is2D):
+def createFixedChoiceComboBox(param, item_row):
+    """
+    Determines whether param is a fixed-choice parameter, modifies items in item_row appropriately and returns a combo
+    box containing the fixed choices. Returns None if param is not fixed-choice.
+    
+    item_row is a list of QStandardItem objects for insertion into the parameter table. 
+    """
+
+    # Determine whether this is a fixed-choice parameter. There are lots of conditionals, simply because the
+    # implementation is not yet concrete; there are several possible indicators that the parameter is fixed-choice.
+    # TODO: (when the sasmodels implementation is concrete, clean this up)
+    choices = None
+    if type(param.choices) is list and len(param.choices) > 0:
+        # The choices property is concrete in sasmodels, probably will use this
+        choices = param.choices
+    elif type(param.units) is list:
+        choices = param.units
+
+    cbox = None
+    if choices is not None:
+        # Use combo box for input, if it is fixed-choice
+        cbox = AssociatedComboBox(item_row[1], idx_as_value=True)
+        cbox.addItems(choices)
+        item_row[2].setEditable(False)
+        item_row[3].setEditable(False)
+
+    return cbox
+
+def addParametersToModel(model, view, parameters, kernel_module, is2D):
     """
     Update local ModelModel with sasmodel parameters
@@ -72,19 +102,19 @@
     else:
         params = parameters.iq_parameters
-    item = []
+
     for param in params:
         # don't include shell parameters
         if param.name == multishell_param_name:
             continue
+
         # Modify parameter name from <param>[n] to <param>1
         item_name = param.name
         if param in multishell_parameters:
             continue
-        #    item_name = replaceShellName(param.name, 1)
 
         item1 = QtGui.QStandardItem(item_name)
         item1.setCheckable(True)
         item1.setEditable(False)
-        # item_err = QtGui.QStandardItem()
+
         # check for polydisp params
         if param.polydisperse:
@@ -93,4 +123,5 @@
             item1_1 = QtGui.QStandardItem("Distribution")
             item1_1.setEditable(False)
+
             # Find param in volume_params
             for p in parameters.form_volume_parameters:
@@ -99,5 +130,4 @@
                 width = kernel_module.getParam(p.name+'.width')
                 ptype = kernel_module.getParam(p.name+'.type')
-
                 item1_2 = QtGui.QStandardItem(str(width))
                 item1_2.setEditable(False)
@@ -110,21 +140,27 @@
                 poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5])
                 break
+
             # Add the polydisp item as a child
             item1.appendRow([poly_item])
+
         # Param values
         item2 = QtGui.QStandardItem(str(param.default))
-        # TODO: the error column.
-        # Either add a proxy model or a custom view delegate
-        #item_err = QtGui.QStandardItem()
         item3 = QtGui.QStandardItem(str(param.limits[0]))
         item4 = QtGui.QStandardItem(str(param.limits[1]))
-        item5 = QtGui.QStandardItem(param.units)
+        item5 = QtGui.QStandardItem(str(param.units))
         item5.setEditable(False)
-        item.append([item1, item2, item3, item4, item5])
-    return item
-
-def addSimpleParametersToModel(parameters, is2D):
-    """
-    Update local ModelModel with sasmodel parameters
+
+        # Check if fixed-choice (returns combobox, if so, also makes some items uneditable)
+        row = [item1, item2, item3, item4, item5]
+        cbox = createFixedChoiceComboBox(param, row)
+
+        # Append to the model and use the combobox, if required
+        model.appendRow(row)
+        if cbox is not None:
+            view.setIndexWidget(item2.index(), cbox)
+
+def addSimpleParametersToModel(model, view, parameters, is2D):
+    """
+    Update local ModelModel with sasmodel parameters (non-dispersed, non-magnetic)
     """
     if is2D:
@@ -132,5 +168,5 @@
     else:
         params = parameters.iq_parameters
-    item = []
+
     for param in params:
         # Create the top level, checkable item
@@ -139,13 +175,21 @@
         item1.setCheckable(True)
         item1.setEditable(False)
+
         # Param values
         # TODO: add delegate for validation of cells
         item2 = QtGui.QStandardItem(str(param.default))
-        item4 = QtGui.QStandardItem(str(param.limits[0]))
-        item5 = QtGui.QStandardItem(str(param.limits[1]))
-        item6 = QtGui.QStandardItem(param.units)
-        item6.setEditable(False)
-        item.append([item1, item2, item4, item5, item6])
-    return item
+        item3 = QtGui.QStandardItem(str(param.limits[0]))
+        item4 = QtGui.QStandardItem(str(param.limits[1]))
+        item5 = QtGui.QStandardItem(str(param.units))
+        item5.setEditable(False)
+
+        # Check if fixed-choice (returns combobox, if so, also makes some items uneditable)
+        row = [item1, item2, item3, item4, item5]
+        cbox = createFixedChoiceComboBox(param, row)
+
+        # Append to the model and use the combobox, if required
+        model.appendRow(row)
+        if cbox is not None:
+            view.setIndexWidget(item2.index(), cbox)
 
 def markParameterDisabled(model, row):
Index: src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
===================================================================
--- src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision f84d793343c420fd47b44c3b601e90f9e82ea451)
+++ src/sas/qtgui/Perspectives/Fitting/FittingWidget.py	(revision 04f775db13543cbc91b64834af6068a163b77f8b)
@@ -2050,8 +2050,11 @@
 
         # Update the QModel
-        new_rows = FittingUtilities.addParametersToModel(self.model_parameters, self.kernel_module, self.is2D)
-
-        for row in new_rows:
-            self._model_model.appendRow(row)
+        FittingUtilities.addParametersToModel(
+                self._model_model,
+                self.lstParams,
+                self.model_parameters,
+                self.kernel_module,
+                self.is2D)
+
         # Update the counter used for multishell display
         self._last_model_row = self._model_model.rowCount()
@@ -2071,11 +2074,17 @@
         self.kernel_module = MultiplicationModel(form_kernel, structure_kernel)
 
-        new_rows = FittingUtilities.addSimpleParametersToModel(structure_parameters, self.is2D)
-        for row in new_rows:
-            self._model_model.appendRow(row)
-            # disable fitting of parameters not listed in self.kernel_module (probably radius_effective)
-            if row[0].text() not in self.kernel_module.params.keys():
-                row_num = self._model_model.rowCount() - 1
-                FittingUtilities.markParameterDisabled(self._model_model, row_num)
+        # Update the QModel
+        FittingUtilities.addSimpleParametersToModel(
+                self._model_model,
+                self.lstParams,
+                structure_parameters,
+                self.is2D)
+
+        # Any parameters removed from the structure factor when producing the product model, e.g. radius_effective, must
+        # be disabled (greyed out, etc.)
+        for r in range(self._last_model_row, self._model_model.rowCount()):
+            param_name = self._model_model.item(r, 0).text()
+            if param_name not in self.kernel_module.params.keys():
+                FittingUtilities.markParameterDisabled(self._model_model, r)
 
         # Update the counter used for multishell display
