Archive for the ‘ASP.NET’ Category

Loading a Dropdown in Gridview Edit Mode

Posted: 16th April 2013 in ASP.NET
Tags:

I’ve just came across and strange phenomenon when using a grid view control. The scenario I encountered occurred when the edit event was fired

Scenario:

To allow items to be added to the grid view I added a text box and a dropdown to the footer which works fine.

However, if, at a future date, I needed to edit the added item I need to load the dropdown into the row being edited and set the previously selected item.  In principal this seemed fairly straight forward by just checking the RowState on the RowDataBound event to see if it was in edit mode (DataControlRowState.Edit).  In practice this only worked on every second/alternate row. 

It turns out you have to use a bitwise comparison to get it to work as seen in the Row Data Bound code below

Row Data Bound
  1. protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)
  2.         {
  3.             GridView gridView = (GridView)sender;
  4.             if (e.Row.RowType == DataControlRowType.EmptyDataRow || e.Row.RowType == DataControlRowType.Footer || (e.Row.RowState & DataControlRowState.Edit) > 0)
  5.             {
  6.                 DropDownList categoryDropDownList = e.Row.FindControl("CategoryDropDownList") as DropDownList;
  7.                 this.BindCategoryDropDown(categoryDropDownList);
  8.                 if (e.Row.RowState == DataControlRowState.Edit)
  9.                 {
  10.                     var teamUpdate = e.Row.DataItem as TeamUpdate;
  11.                     if (categoryDropDownList != null && teamUpdate != null)
  12.                     {
  13.                             categoryDropDownList.Items.FindByText(teamUpdate.Category).Selected = true;
  14.                     }
  15.                 }
  16.             }

Bind Dropdown
  1. /// <summary>
  2.       /// Binds the category drop down.
  3.       /// </summary>
  4.       /// <param name="dropDownList">The drop down list.</param>
  5.       private void BindCategoryDropDown(DropDownList dropDownList)
  6.       {
  7.           if (dropDownList == null)
  8.           {
  9.               return;
  10.           }
  11.  
  12.           dropDownList.DataSource = this.ReportCategories;
  13.           dropDownList.DataValueField = "Key";
  14.           dropDownList.DataTextField = "Value";
  15.           dropDownList.DataBind();
  16.       }

 

So,in short, use:

(e.Row.RowState & DataControlRowState.Edit) > 0)

not

e.Row.RowState == DataControlRowState.Edit

Cheers Smile

 

Okay, I’ve not blogged for sometime. So here a quick one just as a memory jogger for myself.

I needed to add a SharePoint URL field to a GridView to display data from a SP link list.  Here’s how i did it.

Code Snippet
  1. <asp:TemplateField>
  2.                         <HeaderTemplate>
  3.                           Title
  4.                         </HeaderTemplate>
  5.                         <ItemTemplate>
  6.                             <asp:Hyperlink NavigateUrl='<%#DataBinder.Eval(Container.DataItem, "URL").ToString().Split(new string[] {", "}, StringSplitOptions.RemoveEmptyEntries)[0]%>' Text='<%#DataBinder.Eval(Container.DataItem, "URL").ToString().Split(new string[] {", "}, StringSplitOptions.RemoveEmptyEntries)[1]%>' runat="server"></asp:Hyperlink>
  7.                         </ItemTemplate>
  8.                     </asp:TemplateField>

I know its not rocket science and there’s probably a better way to do it, but a least I won’t have to trawl through Google again to find the answer.

More to come soon. Need to get back into blogging…

Recently, I came across a problem where I had to dynamically add a hidden user control into the ContentTemplate of an ASP.NET AJAX accordion control.  This, was over complicated, by the fact that this accordion was nested in a tab control and getting some data synchronously and some asynchronously. 

One of the problems I faced was the usual control manipulation in the Page_Load event! By this I mean checking to see if the Page.IsPostBack to ensure your not loading the controls again.

This particular problem related to drop down lists. 

After several unsuccessful attempts to get the logic just right, I decided to revisit the ASP.NET Page Life Cycle to refresh my memory as to what was going on.

As its been a while since I’d came across this situation, I had forgotten all about Page_Init, which happens before the View State is loaded.

So, by loading all the dropdowns in Page_Init i was able to retrieve the correct values every time in the Event handler of the button click which caused the post back.

I know this means the dropdowns are loaded on postback too, but I feel this method is far easier and cleaner than checking the Page.IsPostBack property in the Page_Load event. 

Scenario: You have build a user control with a button and now you wish to embed the control onto you page. However, you want to handle the click event of the button on the main page, not in the control.

Solution: To do this, you need to expose the event handler of the user control button’s click event and wire it up to internal working of the user control click event handler/delegate.

This can be done using the following code extracts:

First, add the control to the user control

Adding the button
  1. <%@ Control Language=”C#” AutoEventWireup=”true” CodeBehind=”EventHanderClick.ascx.cs” Inherits=”UserControlEventHandlerTest.EventHanderClick” %>
  2. <asp:Button ID=”Button1″ runat=”server” Text=”Button” OnClick=”AddNewButton_Click”/>

Next, we need to expose the events in the code behind of the user control.

User Control Code Behind
  1. protected void Page_Load(object sender, EventArgs e)
  2. {
  3. if (!string.IsNullOrEmpty(this.OnAddNewClientClick))
  4. this.Button1.Attributes.Add(“onclick”, string.Format(“{0}; return false;”, this.OnAddNewClientClick));
  5. }
  6. public string OnAddNewClientClick
  7. {
  8. get;
  9. set;
  10. }
  11. private static readonly object AddNewClickEvent = new object();
  12. public event EventHandler AddNewClick
  13. {
  14. add
  15. {
  16. Events.AddHandler(AddNewClickEvent, value);
  17. }
  18. remove
  19. {
  20. Events.RemoveHandler(AddNewClickEvent, value);
  21. }
  22. }
  23. protected void AddNewButton_Click(object sender, EventArgs e)
  24. {
  25. OnAddNewButtonClick(EventArgs.Empty);
  26. }
  27. protected virtual void OnAddNewButtonClick(EventArgs e)
  28. {
  29. var addNewEventDelegate =
  30. (EventHandler)Events[AddNewClickEvent];
  31. if (addNewEventDelegate != null)
  32. addNewEventDelegate(this, e);
  33. }

It can also be seen, above, that an OnAddNewClientClick property has been exposed as a string. This is to allow you to wire up a JavaScript function. Notice too, I have used string.Format to add the onclick attribute to the control and concatenated return false; onto the end. This is to prevent the control from posting back, if the on client click event is being used.

Now, we can go to the main page and add the newly defined user control.  If you now go to the source view you will notice that both events have been exposed and are picked up in the intellisense

User Control Source
  1. <uc1:ClickEventTestControl ID=”ClickEventTestControl1″ runat=”server” OnAddNewClick=”UserControlButtonEvent” OnAddNewClientClick=”alert();” />
User Control Event
  1. protected void UserControlButtonEvent(object sender, EventArgs e)
  2. {
  3. this.Label1.Text = “Fired by the user control click event”;
  4. }

Now, when you  click the button on the user control, which has been added to the page, the code on the page is used.