Question

I have a ListView that displays a shopping cart. It was working fine until I added the String.Format to display the LineTotal decimal as a currency string. It was working when I just had an Eval on LineTotal.

The problem happens when I add the String.Format--it messes up the codebehind. Error: Input string was not in a correct format.

In the C#, I take the value of the text label and use that throughout the codebehind to do things like add up the total value (sum var) of products.

I want the PriceLabel price to display as currency, but ALSO to be able to use the value of the label in my Listview databound function as well so that I can update the sum var.

Abbreviated ItemTemplate:

<ItemTemplate>               
<asp:Label ID="PriceLabel" runat="server" Text='<%# String.Format("{0:C}", Eval("LineTotal"))%>' ></asp:Label>
</ItemTemplate>

Codebehind:

    protected void ProductListView_ItemDataBound(object sender, ListViewItemEventArgs e)
        {
        if (e.Item.ItemType == ListViewItemType.DataItem)
            {
            //update subtotal by finding the label string value
            Label lbl = (Label)e.Item.FindControl("PriceLabel") as Label;

            decimal sublinetotal = Convert.ToDecimal(lbl.Text);// <---- Input error here

            //update the sum var to show the total price on the page
            sum += sublinetotal;

            }
        }
Was it helpful?

Solution

I think your approach is not really good in this case.

Firstly, the error you got is because lbl.Text is probably empty since the binding is being made (see, the value in the ASPX file will be set AFTER ItemDataBound event). So, you'd be better to set read the DataItem directly:

var row = e.Item.DataItem as System.Data.DataRowView;
if (row != null) {
  sum += row["LineTotal"];
}

See: http://msdn.microsoft.com/en-us/library/bb299031.aspx for more information.

However, a more robust approach would be to calculate this BEFORE any data binding. So, this would be reusable, and the view wouldn't have to calculate all this:

public class InvoiceLine {
  public Decimal Line { get; set; }
}

public class Invoice {
  public IList<InvoiceLine> Lines { get; set; }
  public Decimal Total {
    get {
      return Lines.Sum(l => l.Line);
    }
  }
}

protected void Page_Load(...) {
  var invoice = SomeInvoiceService.GetInvoice(id);
  ProductListView.DataSource = invoice.Lines;
  ProductListView.DataBind();

  TotalLabel.Text = String.Format("{0:C}", invoice.Total);
}

ASPX FILE:

<asp:ListView ID="ProductListView" runat="server">
  <ItemTemplate>
    <%# String.Format("{0:C}", Eval("Line")); %>
  </ItemTemplate>
</asp:ListView>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top