SalesLogix Web Client- Add Opportunity/SalesOrder Product grid: Binding a data grid drop down column programmatically

In the standard add product screen for both an Opportunity and Sales Order, the user is able to perform in-line edits to the selected products.  One of the columns that can be edited is the Price Level column.  By default this column is a picklist column showing the “Price Description” picklist. 

 Standard Add Product screen showing picklist selection in edit mode

The problem with binding the picklist to this column is that not every product contains each price level. This can lead to confusion for a user when they are not sure which of the choices in the list are valid for the given product.   In order to filter the column’s choices we can change the column to be a drop down list and programmatically bind the list based upon the selected record’s defined price levels.  Lets take a look at how to do this.

The sales order and opportunity add screens are both custom smart parts. 
Each smart part is comprised of an ascx and a corresponding cs file.  These
files can be found in the Application Architect under the Portal
Manager…SalesLogix Client…Support Files…Smart Parts and then either Opportunity
or SalesOrder.  The Opportunity files are called “AddOpportunityProduct” and the
Sales Order ones, called “AddSalesOrderProduct:”.  In this post, I will
demonstrate the steps on the Opportunity version.

The first step is to alter
the ascx file and change the grid’s column definitions.

In the file you want to look for the Price Program column within the
asp:GridView control. In a standard 7.5.3 system the column definition is on
line 129 of the file.  It should look like this:

<asp:TemplateField HeaderText=”<%$ resources: grdProducts.PriceLevel.ColumnHeader %>”>
    <ItemTemplate>
        <SalesLogix:PickListControl PickListName=”Price Description” runat=”server” ID=”pklProgramDisplay”
            style=’white-space:nowrap;’ OnPickListValueChanged=’pklProductProgram_PickListValueChanged’
            AutoPostBack=”false” DisplayMode=”AsText” PickListValue='<%# Eval(“Program”) %>’ />
    </ItemTemplate>
    <EditItemTemplate>
        <SalesLogix:PickListControl PickListName=”Price Description” runat=”server” ID=”pklProgram”
            style=’white-space:nowrap;’ OnPickListValueChanged=’pklProductProgram_PickListValueChanged’
            AutoPostBack=”true” DisplayMode=”AsHyperlink” PickListValue='<%# Bind(“Program”) %>’ />
    </EditItemTemplate>
</asp:TemplateField>

Again, we are going to change this from a SalesLogix picklist control to a standard drop down.  To do this we change the entire TemplateField markup to look like this:

<asp:TemplateField HeaderText='<%$ resources: TFProgram_rsc.HeaderText %>’ >
    <ItemTemplate>
        <%# Eval(“Program”) %>
    </ItemTemplate>
    <EditItemTemplate>
        <asp:DropDownList ID=”dropProgram” rows=”4″ runat=”server” style=’white-space:nowrap;’ AutoPostBack=’true’
        OnSelectedIndexChanged=”dropProgram_IndexChanged” AppendDataBoundItems=”true” Text='<%# Bind(“Program”) %>’ DataSource='<%# getPrograms(Eval(“Product.Id”)) %>’ DataTextField=”Program” DataValueField=”Program”  />
    </EditItemTemplate>
</asp:TemplateField>
 

You can see in our new markup we have simplified the ItemTemplate component to simply display the text corresponding to the Program property. 

In the EditItemTemplate section we have switched the control to a standard asp.net DropDownList.  A couple of notes about the attributes I have specified:

  • Rows=”4” This defines that four items will display when the drop down appears.  You can expand this as needed.

  • OnSelectedIndexChnaged=”dropProgram_IndexChanged” This defines the server side code to run when a user selects an item from the list.  This code will be placed in the corresponding cs file and will be what actually sets the price accordingly.
  • AppendDataBoundItems=”true” This must be set in order to allow the drop down to accept items added dynamically.
  • Text='<%# Bind(“Program”) %>’ Specifies what property from the underlying datasource will display as the selected value when an item is chosen.
  • DataSource='<%# getPrograms(Eval(“Product.Id”)) %>’ This defines how the drop down list is bound.  We are calling the getPrograms method.  This method will again be added to the cs file and is what controls the choices in the list.
  • DataTextField and DataValueField=”Program” this defines the datasource properties used to actually fill the list with entries.

 The next thing we need to do is to add a hidden field bound to the selected rows Product ID.  This is so we can use this information from the code behind.  To do this we simply add a new field within the columns markup for the grid, like so:

                         <asp:TemplateField>
                            <ItemTemplate>
                                <asp:Label ID=”lblProdID” runat=”server” Text='<%# Eval(“Product.Id”) %>’ Visible=”false” />
                            </ItemTemplate>
                            <EditItemTemplate>
                                <asp:HiddenField ID=”hidProductId” runat=”server” Value='<%#Eval(“Product.Id”) %>’ />
                            </EditItemTemplate>
                        </asp:TemplateField>

That is all we need to do in the ascx file.  We now have changed the column to the desired drop down list instead of a SalesLogix picklist.

Onto the cs file.  In the cs file we need to add our two methods refrenced in our new ascx markup “getPrograms” and “dropProgram_IndexChanged.  In the cs file we can add this code like so:      

    protected System.Collections.Generic.IList<Sage.Entity.Interfaces.IProductProgram> getPrograms(object ProductId)
    {
        System.Collections.Generic.IList<Sage.Entity.Interfaces.IProductProgram> programs = new List<Sage.Entity.Interfaces.IProductProgram>();
        if(ProductId!=null)
        {
            Sage.Platform.RepositoryHelper<Sage.Entity.Interfaces.IProductProgram> repository =
            Sage.Platform.EntityFactory.GetRepositoryHelper<Sage.Entity.Interfaces.IProductProgram>();
            Sage.Platform.Repository.ICriteria criteria = repository.CreateCriteria();
            criteria.Add(repository.EF.Eq(“Product.Id”,ProductId.ToString()));
            criteria.AddOrder(repository.EF.Asc(“Program”));
            programs = criteria.List<Sage.Entity.Interfaces.IProductProgram>();                        
        }
        return programs;
    }

 

The getPrograms routine accepts a parmeter passing in the Product ID of the row being edited.  It then uses IRepository to find the programs associated to that Product ID.  With the programs found it returns an IList of the ProductProgram interface.

    protected void dropProgram_IndexChanged(object sender, EventArgs e)
    {
        IOpportunity opportunity = BindingSource.Current as IOpportunity;
            string productId = ((HiddenField) grdProducts.Rows[grdProducts.EditIndex].FindControl(“hidProductId”)).Value;
            string program = ((DropDownList) grdProducts.Rows[grdProducts.EditIndex].FindControl(“dropProgram”)).SelectedValue;       
            foreach(IOpportunityProduct op in opportunity.Products)
              {
                    if(op.Product.Id.ToString() == productId)
                    {
                        op.Program = program;
                        Sage.SalesLogix.Opportunity.Rules.CalcPriceFromProgramPrice(op);
                        break;
                }
              }   
    }

The dropProgram_Index change event looks at what the selected value is of the dropProgram column and then finds the price information for that price level and sets the current opportunity record with the newly selected price program pricing.  To do this I used a standard Opportunity entity business rule which takes care of setting the Opportunity Price, CalcPrice, and ExtendedPrice properties.

 

ABOUT THE AUTHOR

Kris Halsrud

Kris Halsrud is a Senior Analyst / Developer for Customer FX Corporation.

1 Comment

  1. Fen, there is a method in the OpportunityProductEx.ascx.cs called OnAddEntityBindings() that defines the fields in the datasource that are available as columns. You would need to add fields to the datasource definition in order to add them as columns.

    Reply

Submit a Comment

Your email address will not be published. Required fields are marked *

Subscribe To Our Newsletter

Join our mailing list to receive the latest Infor CRM (Saleslogix) news and product updates!

You have Successfully Subscribed!