p2p.wrox.com Forums

p2p.wrox.com Forums (http://p2p.wrox.com/index.php)
-   ASP.NET 3.5 Basics (http://p2p.wrox.com/forumdisplay.php?f=351)
-   -   ItemDataBound on ListView (http://p2p.wrox.com/showthread.php?t=74780)

westannex June 13th, 2009 02:48 PM

ItemDataBound on ListView
 
Hello,

I'm trying to convert an example of a RowDataBound event for a GridView, to an ItemDataBound event for a ListView.

This is what I'm starting with:

protected void gridProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string prodtype = (string)DataBinder.Eval(e.Row.DataItem, "ProductType");
if (prodtype == "Sample" )
etc.


This is as far as I get on the conversion:

protected void listProducts_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
string prodtype = (string).....

Where do I go next?


Thanks,

David.

philip_cole June 13th, 2009 03:12 PM

Cast to ListViewDataItem
 
Hi David,

In the ItemDataBound event for items which are ListViewItemType.DataItem, e.Item is of type ListViewDataItem. You can cast e.Item to this and then use its DataItem property the same as with the GridView. The example on msdn at http://msdn.microsoft.com/en-us/libr...wdataitem.aspx is similar.

So your code could be:
Code:

protected void listProducts_ItemDataBound(object sender, ListViewItemEventArgs e)
{
  if (e.Item.ItemType == ListViewItemType.DataItem)
  {
    ListViewDataItem dataItem = (ListViewDataItem)e.Item;
    string prodtype = (string)DataBinder.Eval(dataItem, "ProductType");
    // ...
  }
}

HTH
Phil

Lee Dumond June 13th, 2009 04:57 PM

Sorry Phillip, there is a slight error in your code. [:)]

Code:

protected void listProducts_ItemDataBound(object sender, ListViewItemEventArgs e)
{
  if (e.Item.ItemType == ListViewItemType.DataItem)
  {
      ListViewDataItem dataItem = (ListViewDataItem) e.Item;
      string prodtype = (string) DataBinder.Eval(dataItem.DataItem, "ProductType");
      if (prodtype == "Sample")
      {
        // do your thing here
      }
  }
}

You got the right idea though.

westannex June 14th, 2009 02:35 PM

Thanks for that. It seems that I overestimated my own abilities to continue from there!

What I want to do is change the value in one column depending on the value in another, as the row is being built.

I thought I could use:
string prodtype = (string) DataBinder.Eval(dataItem.DataItem, "ProductType");
if (prodtype == "Sample")
{
(string) DataBinder.Eval(dataItem.DataItem, "ProductText") = "Sample product";
}

where ProductType and ProductText are the 2 columns.

But the page wont run with this code.

Lee Dumond June 14th, 2009 04:24 PM

Two reasons for the problem you're having:

1. The Eval method just evaluates the databinding method. It does not allow you to change the value.

2. The ItemDataBound event is too late to change any of the values anyway, because they are already bound when this event fires.

In order to do this, you need to handle the ItemCreated event. Then, you need to modify the DataRowView that is being used to display the item.

Code:

protected void listProducts_ItemCreated(object sender, ListViewItemEventArgs e)
{
  if (e.Item.ItemType == ListViewItemType.DataItem)
  {
      ListViewDataItem dataItem = (ListViewDataItem) e.Item;
      string prodtype = (string) DataBinder.Eval(dataItem.DataItem, "ProductType");
 
      DataRowView view = (DataRowView)dataItem.DataItem;
 
      if (prodtype == "Sample")
      {
        view["ProductText"] = "Sample product";
      }
  }
}


philip_cole June 15th, 2009 12:10 PM

Sorry Lee, there is a slight error in your code. [:p]

OK I had to dig deep to find it, but it's worth mentioning that ItemCreated is raised each time the layout of the ListView is created, not just when databinding happens. For example if you do a postback later on, ItemCreated will be raised but DataItem won't have a value, so when you try to set view["ProductText"] it will raise a NullReferenceException.

So you just need to add a null check to your ItemCreated event:
Code:

protected void listProducts_ItemCreated(object sender, ListViewItemEventArgs e)
{
  if (e.Item.ItemType == ListViewItemType.DataItem)
  {
      ListViewDataItem dataItem = (ListViewDataItem) e.Item;

      if(dataItem.DataItem != null)
      {

        string prodtype = (string) DataBinder.Eval(dataItem.DataItem, "ProductType");
 
        DataRowView view = (DataRowView)dataItem.DataItem;
 
        if (prodtype == "Sample")
        {
            view["ProductText"] = "Sample product";
        }
      }
  }
}

Phil

Lee Dumond June 15th, 2009 12:26 PM

Phil,

You sure about that? Remember, the ListView is going to be re-bound on postbacks.

I just tried this on my end (Northwind database) with a button to postback the page, and encountered no problems.

philip_cole June 15th, 2009 01:05 PM

Indeed, depending on how it is bound. But remember ItemCreated is also raised before Page_Load on each request, so update events etc can be raised, at which point it will not be binding.
It works in this case because DataBinder.Eval returns null, and so if(prodtype=="Sample") returns false.

If you change it to something like this, you will get an exception:
Code:

if (prodtype == "Sample" || prodtype == null)
{
    view["ProductText"] = "Sample product";
}


Lee Dumond June 15th, 2009 01:45 PM

Sorry Phil, I'm not following you.

DataItem is not going to be null as long as the item type is ListViewItemType.DataItem, and we are checking for that.

And if the item type is ListViewItemType.DataItem, prodtype will never be null as long as there is data in that field.

Not sure where you are getting the "ItemCreated is also raised before Page_Load on each request" thing. Certainly not on MSDN.

westannex June 15th, 2009 03:06 PM

Phil, Lee,

Thanks for your help.

Dave.


All times are GMT -4. The time now is 06:09 AM.

Powered by vBulletin®
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
© 2013 John Wiley & Sons, Inc.