Solved

DataList ItemCommand event not firing when ImageButton clicked

Posted on 2006-11-09
15
4,050 Views
Last Modified: 2008-01-09
Hi,

I have the follwing class (Template), which inherits from UserControl.  It contains a DataList with an ItemTemplate that among other things adds an ImageButton control to the container.  

The Template user control itself is used in a third party datagrid called HierarGrid ( http://aspalliance.com/articleViewer.aspx?aId=21&pId= ).  The basic idea is that this UserControl is used as a template to display related data for each row in a standard datagrid, in a drop-down format.  The important things here is that the method OnDataTableDataBind() is called for each item of the primary datagrid on DataBinding of the user control, and has an argument that contains a DataTable that represents the child data for that item.

The following code is obviously a cut-down version, but the problem that I am having is that when you click on the ImageButton.  The ItemCommand event of the DataList is not firing.  

public class Template : System.Web.UI.UserControl
{
   
   protected System.Web.UI.WebControls.DataList DataList1;

   protected override void OnInit(EventArgs e)
   {
      this.DataList1.ItemCommand += new System.Web.UI.WebControls.DataListCommandEventHandler(this.DataList1_ItemCommand);
   }

   private void DataList1_ItemCommand(object sender, DataListCommandEventArgs args)
   {
      ... // DOES NOT FIRE
   }
      
   // CALLED ON DataBinding ...
   protected override void OnDataTableDataBind(ExpandingTemplateDataTableDataBindEventArgs args)
   {
      base.OnDataTableDataBind(args);
      DataList1.ItemTemplate = new DatalistLabelColumn();
      DataList1.DataSource = args.Table;
   }


   public class DatalistLabelColumn : ITemplate
   {
      ...
      public void InstantiateIn(Control container)
      {
         ImageButton imgAdd = new ImageButton();
         imgAdd.CommandName = "Add";
         imgAdd.ImageUrl = @"~/image.gif";
         ...
         container.Controls.Add(imgAdd);
      }
   }

}

Can anyone think of anything that could cause this?

Cheers,
Steve
      
0
Comment
Question by:steve_bagnall
  • 7
  • 7
15 Comments
 
LVL 28

Expert Comment

by:strickdd
ID: 17907394
Are you sure you have the ItemCommand method bound to the datagrid control?
0
 
LVL 28

Expert Comment

by:mmarinov
ID: 17907420
Hi steve_bagnall,

when have you bind the datalist control? this behaviour is common when in postback you bind the control again - in this scenario the viewstate lose the informaction about the clicked button and will never rise the event


Cheers!
0
 
LVL 5

Author Comment

by:steve_bagnall
ID: 17907616
I don't data bind on page load, the containing datagrid is databound in an initialise method that is called in response to the handling of an ItemCommand elsewhere in the application.  I have overriden the OnDataBinding method and stuck a break-point on the call to the base implementation, and the UserControl is databound before I click the button, but does not get databound again after.  Is this what you mean?
0
 
LVL 28

Expert Comment

by:mmarinov
ID: 17912673
If i understand you correct (i do not have the complete code to be sure) the grid is bound every time (on first open and after post back).
If this is correct - then you have to bind ONLY on the first open

regards
0
 
LVL 5

Author Comment

by:steve_bagnall
ID: 17912776
I have put a break-point on the databinding handler for both the datagrid and the template, and the break points are hit when the page first loads, but after I have clicked the ImageButton on the template the page just posts back, without the ItemCommand event firing and without the breakpoints on either of the databinding event handlers being hit.  So I'm pretty sure that neither the grid nor the template are being bound after I click the button.

Unfortunately the code that causes the initial databinding is spread out over a number of files, but I will try and summarise:-

When the page loads for the first time, the control that contains the control that contains the datagrid calls an Initialise() method of the containing control.
{
   This method (among other things) calls the Initialise() method of the datagid (I have made the HierarGrid above extend an already extended version of the   DataGrid that has an initialise method).
   {
      This Initialise method gets the datasource for the datagrid and stores it as a property (including more that one table with Relations that allow the Hierargrid to know what the drop-down information should be)
   }
   Then the UpdateRules() method of the datagrid is called.
   {
      this assigns the datasource to the datagrid and calls DataBind() on the datagrid.  This causes the DataBinding handlers of the datagrid and the template to fire in that order.
   }
   Initialise exits
}

Clicking the ImageButton simply causes the page to post back seemingly without firing the ItemCommand event.

Hope this is clear,

Cheers, Steve
0
 
LVL 28

Expert Comment

by:mmarinov
ID: 17912829
I am ok with this description but what happens when the page is postback? You gave me the scenario on first load.
As i say before if on postback the datagrid is reinitialized again and bind again the datagrid loses its state before submittion and don't know that something in it is causing the postback

mmarinov
0
 
LVL 5

Author Comment

by:steve_bagnall
ID: 17912898
No when it posts back nothing is bound again, the only thing that happens is that the event handlers are reattached
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
LVL 28

Expert Comment

by:mmarinov
ID: 17912925
can you post the code in some way ?
mmarinov
0
 
LVL 5

Author Comment

by:steve_bagnall
ID: 17912960
Not really in a way that you will be able to run it yourself, it relies on referenced assembies and web services and stuff.  Is there a particular part of it where you think the problem may lie, and I can post that?
0
 
LVL 28

Expert Comment

by:mmarinov
ID: 17912985
Because i do not have the code i'm thinking like this: the control may do not fire an event if it looses its state
the state can be loses in 2 major scenarious (not only 2 but these are major): when it is dynamic control - which obvious is not your scenario - and the control is not recreated every time and the second one when it state is re-initialized

so i do not need the complete project code - but the files that are neede to check the working process - i do not want to compile it (it will be better but it is ok) i just want to see the code of the page that the control is added, initialized, intialize the events bind the data and the click of the control that MUST rise the itemCommand event

regards
0
 
LVL 5

Author Comment

by:steve_bagnall
ID: 17913091
This is the UserControl: Template, which the Hierargrid uses as the tempate to display the drop-down data and the control in which the ImageButton is created (it is dynamically created b.t.w).  The ImageButton's who's ItemCommand events I am interested in are imgAdd and imgRemove in the DatalistLabelColumn ITemplate:-

public class Template : UserControl
{
      protected System.Web.UI.WebControls.DataList DataList1;
      public delegate void AddRemoveDEventHandler(object sender,
                  ActionDEventArgs args);
      public event AddRemoveDEventHandler AddRemoveD;
      
      protected override void OnPreRender(EventArgs e)
      {
            base.OnPreRender (e);
      }
      protected virtual void OnAddRemoveD(ActionDEventArgs args)
      {
            if (AddRemoveD != null)
            {
                  AddRemoveD(this, args);
            }
      }
      protected override void OnDataBinding(EventArgs e)
      {
            base.OnDataBinding (e);
      }
      private void DataList1_ItemCommand(object sender, DataListCommandEventArgs args)
      {
            OnAddRemoveD(new ActionDEventArgs(DAction.Add, 0, 0));
      }
      private void Page_Load(object sender, System.EventArgs e)
      {
      }
      protected override void OnInit(EventArgs e)
      {
            InitializeComponent();
            base.OnInit (e);
      }
      private void InitializeComponent()
      {
            this.DataList1.ItemCommand += new System.Web.UI.WebControls.DataListCommandEventHandler(this.DataList1_ItemCommand);
            this.Load += new System.EventHandler(this.Page_Load);
      }
      protected override void OnDataTableDataBind(ExpandingTemplateDataTableDataBindEventArgs args)
      {
            base.OnDataTableDataBind(args);
            DataList1.ItemTemplate = new DatalistLabelColumn(
                  this.TemplateColumns,
                  this.KeyValues,
                  this.ColumnNames,
                  this.ColumnsToHide);
            DataList1.DataSource = args.Table;
      }
}

public class DatalistLabelColumn : ITemplate
{
      private const int SPACER_WIDTH = 35;
      private ExpandingColumns _columns;
      private Hashtable _keyValues;
      private ArrayList _columnNames;
      private Hashtable _columnsToHide;

      private Label lblA = new Label();
      private Label lblB = new Label();
      private Label lblC = new Label();
      private Label lblD = new Label();
      private Label lblE = new Label();
      private Label lblF = new Label();
      private Label lblG = new Label();

      private Hashtable _htAllColumns = new Hashtable();

      public DatalistLabelColumn(
            ExpandingColumns Columns,
            Hashtable KeyValues,
            ArrayList ColumnNames,
            Hashtable ColumnsToHide)
      {
            this._columns = Columns;
            this._keyValues = KeyValues;
            this._columnNames = ColumnNames;
            this._columnsToHide = ColumnsToHide;

            lblA.Style.Add("visibility", "hidden");
            lblB.Style.Add("visibility", "hidden");

            lblA.DataBinding += new EventHandler(Handle_lblADataBinding);
            lblB.DataBinding += new EventHandler(Handle_lblBDataBinding);
            lblC.DataBinding += new EventHandler(Handle_lblCDataBinding);
            lblD.DataBinding += new EventHandler(Handle_lblDDataBinding);
            lblE.DataBinding += new EventHandler(Handle_lblEDataBinding);
            lblF.DataBinding += new EventHandler(Handle_lblFDataBinding);
            lblG.DataBinding += new EventHandler(Handle_lblGDataBinding);

            _htAllColumns.Add("AData", lblA);
            _htAllColumns.Add("BData", lblB);
            _htAllColumns.Add("CData", lblC);
            _htAllColumns.Add("DData", lblD);
            _htAllColumns.Add("EData", lblE);
            _htAllColumns.Add("FData", lblF);
            _htAllColumns.Add("GData", lblG);
      }

      public void InstantiateIn(Control container)
      {
            ImageButton imgAdd = new ImageButton();
            ImageButton imgRemove = new ImageButton();
            imgAdd.CommandName = "Add";
            imgAdd.ImageUrl = @"~/images/plus.gif";
            imgAdd.Width = 10;
            imgRemove.CommandName = "Remove";
            imgRemove.ImageUrl = @"~/images/minus.gif";

            int visibleColumnIndex = 0;
            ArrayList alVisibleColumns = new ArrayList();

            for (int j = 0; j < _columnNames.Count; j++)
            {
                  bool hidden = false;
                  foreach (object key in _columnsToHide.Keys)
                  {
                        if (_columnNames[j] == _columnsToHide[key])
                        {
                              hidden = true;
                              break;
                        }
                  }
                  if (! hidden)
                  {
                        alVisibleColumns.Add(_columnNames[j]);
                  }
            }

            Table tblOuter = new Table();
            tblOuter.Width = Unit.Percentage(100);
            tblOuter.Style.Add("border-collapse", "collapse");
            tblOuter.Style.Add("table-layout", "fixed");

            container.Controls.Add(tblOuter);

            TableRow row = new TableRow();
            row.CssClass = "DStyle";
            tblOuter.Rows.Add(row);
            TableCell cell = new TableCell();
            cell.Width = Unit.Pixel(SPACER_WIDTH);
            row.Cells.Add(cell);
            Image image = new Image();
            image.ID = "spacer";
            image.ImageUrl = "~/Images/expanded_row.gif";
            cell.Controls.Add(image);

            cell = new TableCell();
            cell.Width = Unit.Pixel(0);
            cell.Controls.Add((Control)_htAllColumns["AData"]);
            row.Cells.Add(cell);
            cell = new TableCell();
            cell.Width = Unit.Pixel(0);
            cell.Controls.Add((Control)_htAllColumns["BData"]);
            row.Cells.Add(cell);

            for (int j = 0; j < _columns.Count; j++)
            {
                  if ( (_columns[j].IsSpacer) && (j != 0) )
                  {
                        AddSpacerCell(row, _columns[j].ColumnWidth);
                  }
                  else
                  {
                        if ( (j == _columns.Count - 1) &&
                              ((_keyValues["ShowAddRemove"] != null) &&
                              (Convert.ToBoolean(_keyValues["ShowAddRemove"]))) )
                        {
                              cell = new TableCell();
                              if (! _columns[j].WidthUnspecified)
                              {
                                    cell.Width = _columns[j].ColumnWidth;
                              }
                              row.Cells.Add(cell);
                              container.Controls.Add(imgAdd);
                              container.Controls.Add(imgRemove);
                        }
                        else
                        {
                              cell = new TableCell();
                              if (! _columns[j].WidthUnspecified)
                              {
                                    if (j == 0)
                                    {
                                          if (_columns[j].ColumnWidth > SPACER_WIDTH)
                                                cell.Width = Unit.Pixel(_columns[j].ColumnWidth - SPACER_WIDTH);
                                          else
                                                cell.Width = Unit.Pixel(0);
                                    }
                                    else
                                    {
                                          cell.Width = _columns[j].ColumnWidth;
                                    }
                              }
                              row.Cells.Add(cell);

                              cell.Controls.Add((Control)_htAllColumns[(string)alVisibleColumns[visibleColumnIndex]]);
                        }
                        visibleColumnIndex ++;
                  }

            }

      }

      private void AddSpacerCell(TableRow Row, int Width)
      {
            TableCell cell = new TableCell();
            cell.Controls.Add(new LiteralControl("&nbsp;"));
            cell.Width = Unit.Pixel(Width);
            Row.Cells.Add(cell);
      }

      private void Handle_lblADataBinding(object sender, EventArgs e)
      {
            Label lbl = (Label)sender;
            DataListItem  container = (DataListItem)lbl.NamingContainer ;
            lbl.Text = Convert.ToString(DataBinder.Eval(((DataListItem)container).DataItem, "RIndex")) ;
      }

      private void Handle_lblBDataBinding(object sender, EventArgs e)
      {
            Label lbl = (Label)sender;
            DataListItem  container = (DataListItem)lbl.NamingContainer ;
            lbl.Text = Convert.ToString(DataBinder.Eval(((DataListItem)container).DataItem, "BData")) ;
      }

      private void Handle_lblCDataBinding(object sender, EventArgs e)
      {
            Label lbl = (Label)sender;
            DataListItem  container = (DataListItem)lbl.NamingContainer ;
            lbl.Text = Convert.ToString(DataBinder.Eval(((DataListItem)container).DataItem, "CData")) ;
      }

      private void Handle_lblDDataBinding(object sender, EventArgs e)
      {
            Label lbl = (Label)sender;
            DataListItem  container = (DataListItem)lbl.NamingContainer ;
            lbl.Text = Convert.ToString(DataBinder.Eval(((DataListItem)container).DataItem, "DData")) ;
      }

      private void Handle_lblEDataBinding(object sender, EventArgs e)
      {
            Label lbl = (Label)sender;
            DataListItem  container = (DataListItem)lbl.NamingContainer ;
            lbl.Text = Convert.ToString(DataBinder.Eval(((DataListItem)container).DataItem, "EData")) ;
      }
      private void Handle_lblFDataBinding(object sender, EventArgs e)
      {
            Label lbl = (Label)sender;
            DataListItem  container = (DataListItem)lbl.NamingContainer ;
            lbl.Text = Convert.ToString(DataBinder.Eval(((DataListItem)container).DataItem, "FData")) ;
      }
      private void Handle_lblGDataBinding(object sender, EventArgs e)
      {
            Label lbl = (Label)sender;
            DataListItem  container = (DataListItem)lbl.NamingContainer ;
            lbl.Text = Convert.ToString(DataBinder.Eval(((DataListItem)container).DataItem, "GData")) ;
      }
}

0
 
LVL 28

Accepted Solution

by:
mmarinov earned 500 total points
ID: 17913140
Ok, with these words : "it is dynamically created b.t.w" it is a problem that nothing is done via post back. The reason is that when a dynamic control is added dynamic it is not added to the viewstate. After submit the page is getting the saved viewstate and put the controls with their view state on the page.
The scenario of working with dynamic controls is every time (no matter it is first load or post back) the controls must be generated - so the controls can be initialized and after that the viewstate will set every values that is find in the Request object.

mmarinov
0
 
LVL 5

Author Comment

by:steve_bagnall
ID: 17913184
Yeah, I just noticed that the ImageButton is not re-created on post-back.  Do you know the reason that InstantiateIn is not called after the button has been clicked?
0
 
LVL 5

Author Comment

by:steve_bagnall
ID: 17913197
.. because DatalistLabelColumn is created only once on Initialise!  Great Answer .. thanks!
0
 
LVL 28

Expert Comment

by:mmarinov
ID: 17913246
glad that can be in help
regards
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

I have developed many web applications with asp & asp.net and to add and use a dropdownlist was always a very simple task, but with the new asp.net, setting the value is a bit tricky and its not similar to the old traditional method. So in this a…
International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now