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

 

Table Cell Padding and Spacing using CSS

Posted: 11th October 2012 in css
Tags:

Okay folks I’m not going to lie. This is a blatant copy of a post on Stack Overflow, but its something I keep forgetting and one for the memory banks.

Here’s the original post by 2astalavista

DEFAULT:

enter image description here

CELLSPACING:

controls the space between table cells

enter image description here

CELLPADDING:

sets the amount of space between the contents of the cell and the cell wall

enter image description here

BOTH:

enter image description here

BOTH SPECIAL:

enter image description here

http://jsfiddle.net/H4emK/

When trying to set the value a data source element to a Boolean value my first attempt was using ToString() on the Boolean value. To me this seemed like a valid way to set the value as can be seen below.

Setting XPath using ToString
  1. this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:isTaskHighlight", this.NamespaceManager).SetValue(this.IsTaskHighlight.ToString());

However, when I tried to use this I received the following error. 

image

On further investigation I found that the ToString() method on a Boolean returns “True” or “False”, not the lower case “true” or “false” InfoPath is looking for.  

To resolve this I created  local method BooleanToString to return the correct value

Infopath boolean to string
  1. private string BooleanToString(bool isTrue)
  2.         {
  3.             return isTrue ? "true" : "false";
  4.         }

And called it to set the value

Setting XPathNavigator to Bool
  1. this.MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:isTaskHighlight", this.NamespaceManager).SetValue(this.BooleanToString(this.IsTaskHighlight));

job done ! Smile

It’s been a while since I’ve used AJAX, but I came across the error “Script control may not be registered before PreRender” when trying to add a timer control to an User Control embedded in a WebPart. I’m pretty certain I have encountered this error before, but as it took me a little while to resolve I thought I’d better blog about it.

What was I trying to do? Well, I was trying to create a Web Part which created a sort of slideshow of web parts! The idea was to use various web parts, which displayed different charts, by loading them dynamically using an Update Panel, a Timer and an AsyncPostBackTrigger. 

At first, things didn’t go to well and I received the error screen shown below

Script control may not be registered before PreRender 

It turns out that the solution is slightly easier that I expected.  Initially, I added a script manager to the user control but, because the timer control automatically posts back the script manager is not loaded when its is looking for it.

So, to resolve the issue, I added the ScriptManager to the SharePoint master page added a ScriptManagerProxy to the user control and it worked a treat.

User Control HTML
  1.   <asp:ScriptManagerProxy ID="ScriptManagerProxy1"runat="server">
  2. </asp:ScriptManagerProxy>
  3. <asp:Timer ID="Timer1" runat="server" OnTick="Timer1_Tick" Interval="20000">
  4. </asp:Timer>
  5. <asp:UpdatePanel ID="DynamicUpdatePanel" runat="server">
  6.    <Triggers>
  7.         <asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
  8.     </Triggers>
  9.     <ContentTemplate>
  10.         <asp:PlaceHolder ID="DynamicPlaceHolder" runat="server"></asp:PlaceHolder>
  11.     </ContentTemplate>
  12. </asp:UpdatePanel>

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…

Okay, I’ve not done any blogging for a while, been mega busy… But I just came across this problem in a MOSS environment, which after a bit of digging was easily resolved. Just thought I’d share…

While trying to filter a list with a Telerik component. I came across the above error ( also shown in the screen shot below)

image

After looking in the log files I discovered that is was throwing an exception of type ThrowIfMaxHttpCollectionKeysExceeded

Entry in the log file 

Error=Operation is not valid due to the current state of the object.   at System.Web.HttpValueCollection.ThrowIfMaxHttpCollectionKeysExceeded()     at System.Web.HttpValueCollection.FillFromEncodedBytes(Byte[] bytes, Encoding encoding)     at System.Web.HttpRequest.FillInFormCollection()

After a bit of digging it turns out that this is a direct result of an MS update to thwart DOS attacks. As can be seen by the entry on Scott Guthrie’s Blog.  However, in this case, i was trying to fix an internal application so DOS attacks were not an issue.

To fix this issue add the following to the web.config file

<appSettings>
  <add key="aspnet:MaxHttpCollectionKeys" value="Number greater than 1000 until the error goes away" />
</appSettings>

I needed to set this value to 3000 to resolve the issue.   Surprised smile

One of my latest challenges was to display one of the new SharePoint 2010 social fields in a datagrid. At first this was just to display the field, but after the client seen the mouse-over functionality on the list item, they wanted to be able to assign a rating straight from the grid without having to go to the item itself. So, here’s how I went about it.

Firstly I created a custom control call as seen in the code sample below:

Rating Control
  1. [DefaultProperty("Rating")]
  2.     [ToolboxData("<{0}:RatingControl runat=server></{0}:RatingControl>")]
  3.     public class RatingControl : WebControl
  4.     {
  5.         protected override void OnInit(EventArgs e)
  6.         {
  7.             base.OnInit(e);
  8.             Page.RegisterRequiresControlState(this);
  9.         }
  10.  
  11.  
  12.         [Bindable(true)]
  13.         [Category("Binding")]
  14.         [DefaultValue("")]
  15.         [Localizable(true)]
  16.         public SPField RatingField
  17.         {
  18.             get
  19.             {
  20.                 SPField field = (SPField)ViewState["RatingField"];
  21.                 return field;
  22.             }
  23.  
  24.             set
  25.             {
  26.                 ViewState["RatingField"] = value;
  27.             }
  28.         }
  29.  
  30.  
  31.         [Bindable(true)]
  32.         [Category("Binding")]
  33.         [DefaultValue("")]
  34.         [Localizable(true)]
  35.         public int ListItemId
  36.         {
  37.             get
  38.             {
  39.                 return Convert.ToInt32(ViewState["ListItemId"]);
  40.             }
  41.  
  42.             set
  43.             {
  44.                 ViewState["ListItemId"] = value;
  45.             }
  46.         }
  47.  
  48.  
  49.         [Bindable(true)]
  50.         [Category("Binding")]
  51.         [DefaultValue("")]
  52.         [Localizable(true)]
  53.         public Guid ListId
  54.         {
  55.             get
  56.             {
  57.                 Guid id = (Guid)ViewState["ListId"];
  58.                 return id;
  59.             }
  60.  
  61.             set
  62.             {
  63.                 ViewState["ListId"] = value;
  64.             }
  65.         }
  66.  
  67.         protected override void CreateChildControls()
  68.         {
  69.  
  70.             if (this.ChildControlsCreated)
  71.                 return;
  72.  
  73.             
  74.             BaseFieldControl renderingcontrol = this.RatingField.FieldRenderingControl;
  75.             renderingcontrol.ControlMode = SPControlMode.Display;
  76.             renderingcontrol.ListId = this.ListId;
  77.             renderingcontrol.ItemId = this.ListItemId;
  78.             Controls.Add(renderingcontrol);
  79.             this.ChildControlsCreated = true;
  80.            
  81.            
  82.             
  83.        }

Next, after adding a new template column to the datagrid containing a place holder (DataGrid source), then binding the data source to the ListItemCollection returned. 

DataGrid Source
  1. <asp:TemplateColumn>
  2.          <HeaderTemplate>
  3.                 Rating
  4.             </HeaderTemplate>
  5.             <ItemTemplate>
  6.                 <asp:PlaceHolder runat="server" ID="RatingPlaceHolder"></asp:PlaceHolder>
  7.             </ItemTemplate>
  8.         </asp:TemplateColumn>

 

I create a new instance  of the rating control on the girdview OnItemDataBound event receiver and add it to the place holder.

OnItemDataBound
  1. protected void SearchResultsGridView_OnItemDataBound(object sender, DataGridItemEventArgs e)
  2.      {
  3.          if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
  4.          {
  5.              Label lastModifiedLabel = (Label)e.Item.FindControl("LastModifiedLabel");
  6.              lastModifiedLabel.Text = Convert.ToDateTime(DataBinder.Eval(e.Item.DataItem, "ModifiedDate")).ToString("dd-MMM-yyyy");
  7.              PlaceHolder placeHolder = (PlaceHolder)e.Item.FindControl("RatingPlaceHolder");
  8.              ratingControl = new RatingControl();
  9.              ratingControl.RatingField = (SPField)DataBinder.Eval(e.Item.DataItem, "RatingField");
  10.              ratingControl.ListId = (Guid)DataBinder.Eval(e.Item.DataItem, "ListId");
  11.              ratingControl.ListItemId = Convert.ToInt32(DataBinder.Eval(e.Item.DataItem, "Id"));
  12.              placeHolder.Controls.Add(ratingControl);
  13.          }
  14.     }

Job Done!