views:

182

answers:

3

I have the following code in the EditItemTemplate of my FormView:

<tr id="primaryGroupRow" runat="server">
  <td class="Fieldname">Primary Group:</td>
  <td><asp:DropDownList ID="iPrimaryGroupDropDownList" runat="server" DataSourceID="GroupDataSource" CssClass="PageText" 
DataTextField="sGroupName" DataValueField="iGroupID" SelectedValue='<%# Bind("iPrimaryGroup") %>'></asp:DropDownList></td>
</tr>

If I remove the runat="server" for the table row, then the iPrimaryGroup field is bound 100% and passed to the business logic layer properly. However in the case of the code above, it is passed with a value of zero.

Can anyone tell me why this is or how to get around it? This is in a control that needs to hide this table row, based on whether or not an administrator or a regular user is editing it. ie: some fields are admin writeable only and I'd like to hide the controls from the view if the user isn't an admin.

A: 

Have a shot at this:

Remove the runat=server attribute

Define a css class

.hidden{ display:hidden;}

Then set the class attribute based on whether or not the user is an admin

<tr class='<%= if(IsUserAdmin) "" else "hidden" %>' >
Michael M
I'll try this out and let you know. I think it will present a security risk though because the controls will still be sent to the client. Using something like Firebug, they could remove the CSS class and then modify the data in those controls. Those controls handle what security permissions are applied.I'll try it out and let you know, but my suspicion is that it's not quite going to do what I need it to. I really don't want to refactor the code, but will do what needs to be done. Anyone have thoughts on why it works this way?
Mike Taber
+1  A: 

If security is a concern perhaps this might work better

<tr>
  <td colspan='2'>
    <asp:panel runat='server' visible='<%= IsUserAdmin %>'>
      <table>
        <tr>
          <td class="Fieldname">Primary Group:</td>
          <td><asp:DropDownList ID="iPrimaryGroupDropDownList" runat="server" DataSourceID="GroupDataSource" CssClass="PageText" DataTextField="sGroupName" DataValueField="iGroupID" SelectedValue='<%# Bind("iPrimaryGroup") %>'></asp:DropDownList>
          </td>
        </tr>
      </table>
   </asp:panel>
 </td>

If I'm not mistaken any markup within the panel will not be rendered if visible=false

Michael M
Thanks Michael, but the problem is that this is inside a FormView. When the DropDownList is contained within a set of tags that specify runat=server, the bound value for iPrimaryGroup is passed to the back end as a zero, regardless of whether the components are displayed or not. I need to figure a way around this problem because the values aren't being updated.
Mike Taber
Hey Mike, I did some testing on this and found the same problem when the row has the runat=server attribute. Not exactly sure what's going on under the hood there. However, I retrieved the values successfully using the code above.
Michael M
I'm going to give you credit for the attempt and vote up your answer, but I found the real answer and how to get around it.
Mike Taber
A: 

It appears that this functionality is by design, although that's not exactly confirmed.

http://weblogs.asp.net/rajbk/archive/2009/08/03/formview-binding-gotcha.aspx

When using the FormView object, if you have a nested control, then two-way databinding isn't going to work properly. You can access the controls in code, and you can get at the data, but it's just not going to automatically update the value in the back end of your Business Logic Layer(BLL) like it's supposed to.

Fortunately, there's a workaround. The way to get it working is to create an event for ItemUpdating. It will have a signature like this:

protected void frmProfile_ItemUpdating(object sender, FormViewUpdateEventArgs e)

This gives you access to the FormViewUpdateEventArgs, which in turn allows you to make changes to the ObjectDataSource values while they are in flight and before they hit your BLL code, as follows:

protected void frmProfile_ItemUpdating(object sender, FormViewUpdateEventArgs e)
{
    if (frmProfile.FindControl("iPrimaryGroupDropDownList") != null)
    {
        DropDownList iPrimaryGroupDropDownList = ((DropDownList)frmProfile.FindControl("iPrimaryGroupDropDownList"));
        e.NewValues["iPrimaryGroup"] = iPrimaryGroupDropDownList.Text;
    }
}
Mike Taber