Alright, I figured out my problem. I was trying to use members of the ShoppingCart control in the code behind of a ShoppingCartStep control. The ShoppingCart control was not instantiated, and you can't access it from a ShoppingCartStep.
The key to controlling your checkout process is not to modify a step, but to manipulate the parent ShoppingCart control found in CMSModules/Ecommerce/Controls/ShoppingCart/ShoppingCart.ascx.
Specifically, you need to edit the LoadCurrentStep() method in the code behind, which has the following code:
public override void LoadCurrentStep()
{
if ((CurrentStepIndex >= 0) && (CurrentStepIndex < CheckoutProcessSteps.Count))
{
// Shopping cart container
ShoppingCartContainer = pnlShoppingCart;
// Default button settings
ButtonBack.Enabled = true;
ButtonNext.Enabled = true;
ButtonBack.Visible = true;
ButtonNext.Visible = true;
ButtonBack.Text = GetString("general.back");
ButtonNext.Text = GetString("general.next");
if (CurrentStepControl != null)
{
// Display checkout process images
if (DisplayStepImages)
{
LoadCheckoutProcessImages();
}
// Set shopping cart step container
CurrentStepControl.StepContainer = pnlCartStepInner;
// Display current control
pnlCartStepInner.Controls.Clear();
pnlCartStepInner.Controls.Add(CurrentStepControl);
}
else
{
lblError.Visible = true;
lblError.Text = GetString("ShoppingCart.ErrorLoadingStep");
}
}
}
The important part of this method is where it's clearing controls from the pnlCartStepInner panel and then adding in the next step's control. This is the part you want to modify if you're looking to add logic to your checkout process to control the flow of the process.
For example, I was trying to check the user's cart and skip steps if specific products were not present. Here's some sample code for that:
int productID = 0;
int productCount = 0;
private void CheckProduct()
{
// Figure out if the product is in the cart
for (var i = 0; i < ShoppingCartInfoObj.CartItems.Count; i++)
{
if (ShoppingCartInfoObj.CartItems[i].SKUID == 530)
{
// when we find the product, remember its ID
productID = i;
}
else
{
productID = -1;
}
}
// If the product was found, do something.
// In this case, I was saving it to the session state to use it later
if (productID != -1)
{
productCount = ShoppingCartInfoObj.CartItems[brickID].CartItemUnits;
Session.Add("ProductCount", productCount);
}
}
public override void LoadCurrentStep()
{
if ((CurrentStepIndex >= 0) && (CurrentStepIndex < CheckoutProcessSteps.Count))
{
// Shopping cart container
ShoppingCartContainer = pnlShoppingCart;
// Default button settings
ButtonBack.Enabled = true;
ButtonNext.Enabled = true;
ButtonBack.Visible = true;
ButtonNext.Visible = true;
ButtonBack.Text = GetString("general.back");
ButtonNext.Text = GetString("general.next");
if (CurrentStepControl != null)
{
// Display checkout process images
if (DisplayStepImages)
{
LoadCheckoutProcessImages();
}
// Set shopping cart step container
CurrentStepControl.StepContainer = pnlCartStepInner;
//Check if the product exists
CheckProduct();
// here's where I change index if the product isn't found
if(CurrentStepIndex == 3 && productID != -1)
{
// increment index
CurrentStepIndex++;
// Set this to false so the base ShoppingCart class
// will update the CurrentStepControl which is a
// read-only property.
mIsControlLoaded = false;
}
// Display current control
pnlCartStepInner.Controls.Clear();
pnlCartStepInner.Controls.Add(CurrentStepControl);
}
else
{
lblError.Visible = true;
lblError.Text = GetString("ShoppingCart.ErrorLoadingStep");
}
}
}