[SalesForce] Checkbox in datatable does not update boolean in wrapper class

I have a wizard comprising of two visualforce pages, a controller, and a wrapper class. After much messing around I've found the root of the problem I've been having. On the first page of my wizard, the user is presented with a list of products and a checkbox next to each. For this I have a wrapper class with two properties (one being the pricebook entry, and another as the boolean to denote whether the instance is selected).

Anyway, when moving to the second page, which displays another datatable with some input boxes for every instance of my wrapper class with the boolean set to true, the problem presents itself. No matter what I do, it always displays none of them. I checked and if I initialise the wrapper class with the boolean to true they all display, and vice versa if I don't. So the problem is that the value of the boolean (isSelected) is not updating when I click on the checkbox.

I assume with visualforce that because I have set the value of the checkbox to the variable, it will update it. But it doesn't. Does anyone know why?

Controller Class:

public class OpportunityProductsController {

// PROPERTIES
public List<SelectableListProduct> wrappedList { get; set; }
public List<OpportunityLineItem> itemsToAdd { get; set; }
public Opportunity controllingOpp { get; set; }

// CONSTRUCTOR
public OpportunityProductsController() {
    //Init Id
    System.debug('Entering constructor.');
    try {
        System.debug('Entering try statement trying to find the controlling opportunity.');
        controllingOpp = [SELECT Id, Name FROM Opportunity WHERE Id=:ApexPages.currentPage().getParameters().get('oid') LIMIT 1];
    } catch (System.QueryException e) {
        System.debug('Entering catch statement. Unable to locate opportunity.');
        controllingOpp = new Opportunity();
    }

    //Initialise lists.
    wrappedList = new List<SelectableListProduct>();
    itemsToAdd = new List<OpportunityLineItem>();

    //Get a list of pricebook entries.
    List<PricebookEntry> unwrappedEntries = new List<PricebookEntry>();
    unwrappedEntries = [SELECT Id, 
                               Product2.Name,
                               Product2.ProductCode,
                               Product2.Standard_Install_Cost__c,
                               Product2.Standard_Monthly_Cost__c,
                               Product2.Supplier__c
                               FROM PricebookEntry WHERE Product2.IsActive = true];
    System.debug('Unwrapped item query returned ' + unwrappedEntries.size() + ' results.');                                   

    wrappedList = PopulateWrappedList(unwrappedEntries);
    System.debug('Exited PopulateWrappedList. Wrapped list contains ' + wrappedList.size() + ' entries.');

}

List<SelectableListProduct> PopulateWrappedList(List<PricebookEntry> unwrapped) {

    List<SelectableListProduct> returnList = new List<SelectableListProduct>();

    //For each record returned, created a wrapped object and put it in the list.
    for (PricebookEntry entry : unwrapped) {
        SelectableListProduct newSLP = new SelectableListProduct(entry, true);
        returnList.add(newSLP);
    }

    //Sort the list.
    returnList.sort();
    return returnList;
}

List<OpportunityLineItem> PopulateSelectedList(List<SelectableListProduct> wrapped) {

    List<OpportunityLineItem> returnList = new List<OpportunityLineItem>();

    for (SelectableListProduct entry : wrapped) {
        if (entry.isSelected) {
            OpportunityLineItem newOLI = new OpportunityLineItem();
            newOLI.OpportunityId = controllingOpp.Id;
            newOLI.PricebookEntry = entry.cProduct;
            newOLI.UnitPrice = 0;
            newOLI.Install_Cost__c = entry.cProduct.Product2.Standard_Install_Cost__c;
            newOLI.Monthly_Cost__c = entry.cProduct.Product2.Standard_Monthly_Cost__c;
            returnList.add(newOLI);
        }
    }

    returnList.sort();
    return returnList;
}

public PageReference Step1() {
    PageReference pageRef = new PageReference('/apex/SelectNewItems');
    pageRef.setRedirect(false);
    return Page.SelectNewItems;
}

public PageReference Step2() {
    //populate selected products list
    itemsToAdd = PopulateSelectedList(wrappedList);
    System.debug('itemsToAdd populated. List contains ' + itemsToAdd.size() + ' entries.');
    PageReference pageRef = new PageReference('/apex/EditNewItems');
    pageRef.setRedirect(false);
    return pageRef;
}

public PageReference Save() {
    //Attempt to save items.
    try {
        insert itemsToAdd;
    } catch (System.DMLException e) {
        ApexPages.addMessages(e);
        return null;
    }
    //Redir to opp detail page.
    PageReference opportunityPage = new ApexPages.StandardController(controllingOpp).view();
    opportunityPage.setRedirect(true);
    return opportunityPage;
}

public PageReference Cancel() {
    PageReference opportunityPage = new ApexPages.StandardController(controllingOpp).view();
    opportunityPage.setRedirect(true);        
    return opportunityPage;
}    
}

Wrapper Class:

 public class SelectableListProduct implements Comparable
 {
 public Boolean isSelected {get;set;}
 public PricebookEntry cProduct {get;set;}

 public SelectableListProduct(PricebookEntry cProduct, Boolean selected){
      this.cProduct = cProduct;
      this.isSelected = selected;
 }

 public Integer compareTo(Object comparisonObject)
 {
     SelectableListProduct comparisonProduct = (SelectableListProduct)comparisonObject;
     return cProduct.Product2.Name.compareTo(comparisonProduct.cProduct.Product2.Name);
 }
}

VF Page 1:

<apex:page controller="OpportunityProductsController" tabstyle="Opportunity">
<apex:sectionHeader title="Add New Opportunity Products" subtitle="Select Products"/>
<apex:form >
  <apex:pageBlock title="Product List">
     <apex:pageBlockButtons >
         <apex:commandButton action="{!Step2}" value="Next" immediate="true"/>
         <apex:commandButton action="{!Cancel}" value="Cancel"/>
     </apex:pageBlockButtons>
     <!-- PRODUCT LIST -->
     <apex:pageBlockTable value="{!wrappedList}" var="slp">
        <apex:column >
           <apex:inputCheckbox value="{!slp.isSelected}"/>
        </apex:column>
        <apex:column value="{!slp.cProduct.Product2.Name}"/>
        <apex:column value="{!slp.cProduct.Product2.ProductCode}"/>
        <apex:column value="{!slp.cProduct.Product2.Standard_Install_Cost__c}"/>
        <apex:column value="{!slp.cProduct.Product2.Standard_Monthly_Cost__c}"/>
        <apex:column value="{!slp.cProduct.Product2.Supplier__c}"/>
     </apex:pageBlockTable>

  </apex:pageBlock>
</apex:form>
</apex:page>

VF Page 2:

<apex:page controller="OpportunityProductsController" tabStyle="Opportunity">
<apex:sectionHeader title="Add New Opportunity Products" subtitle="Edit Products"/>
<apex:pageMessages />
<apex:form >
    <apex:pageBlock title="Edit Item Information">
        <apex:pageBlockButtons >
            <apex:commandButton action="{!Save}" value="Done"/>
            <apex:commandButton action="{!Step1}" value="Back"/>
            <apex:commandButton action="{!Cancel}" value="Cancel"/>
        </apex:pageBlockButtons>
            <apex:pageBlockTable value="{!itemsToAdd}" var="currentItem">
                <apex:column value="{!currentItem.PricebookEntry.Product2.Name}" />
                <apex:column headerValue="Quantity">
                    <apex:inputField value="{!currentItem.Quantity}"/>
                </apex:column>
                <apex:column headerValue="Install Cost">
                    <apex:inputField value="{!currentItem.Install_Cost__c}" />
                </apex:column>
                <apex:column headerValue="Monthly Cost">
                    <apex:inputField value="{!currentItem.Monthly_Cost__c}" />
                </apex:column>
            </apex:pageBlockTable> 
    </apex:pageBlock>
</apex:form>
</apex:page>

Best Answer

Got it! Turns out the immediate="true" parameter I'd added on suggestion while trying to fix a different issue before was causing problems. All it took was to get rid of that in the command button tag.