ASP.NET Hiding a <asp:Panel>/<th>/<tr>/<td> inside a ListView
<asp:ListView ID="ListView1" runat="server" ItemPlaceholderID="itemHolder"
OnItemCommand="listViewCmd" OnItemDeleting="OnItemDeleting"
OnItemEditing="OnItemEditing">
<LayoutTemplate>
<table class = "tblItemDetail" style = "color:Black;" width="100%" border="0" cellpadding="5">
<tr>
<asp:Panel ID="pnlNameHead" runat="server">
<th id="thName" runat="server">Name
</th>
</asp:Panel>
<th>Address
</th>
<th>Contact No.
</th>
<th>E-mail Address
</th>
<th>Edit
</th>
<th>Delete
</th>
</tr>
<asp:PlaceHolder ID="itemHolder" runat="server"></asp:PlaceHolder>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<asp:Panel ID="pnlName" runat="server">
<td align="center" id="tdName" runat="server">
<asp:Literal ID="lit1" runat="server" Text='<%# Eval("SupplierName") %>'></asp:Literal>
</td>
</asp:Panel>
<td align="center">
<asp:Literal ID="Literal1" runat="server" Text='<%# Eval("SupplierAdd") %>'></asp:Literal>
</td>
<td align="center">
<asp:Literal ID="Literal2" runat="server" Text='<%# Eval("SupplierContact") %>'></asp:Literal>
</td>
<td align="center">
<asp:Literal ID="Literal3" runat="server" Text='<%# Eval("SupplierEmail") %>'></asp:Literal>
</td>
<td align="center">
<asp:Button ID="Button3" runat="server" Text="Edit" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "SupplierID") %>' CommandName="edit" />
</td>
<td align="center">
<asp:Button ID="Button2" runat="server" Text="Delete" CommandArgument='<%# DataBinder.Eval(Container.DataItem, "SupplierID") %>' CommandName="delete" />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
I got this source code for my aspx Web Form. I'm trying to hide the column for the supplier name. I've already tried many ways like:
- ListView1.FindControl("pnlNameHead").Visible = false
- Panel pnlName = (Panel)ListView.FindControl("pnlName");
- pnlName.Visible = false;
but开发者_如何学JAVA I always get "Object reference not set to an instance of an object". Can anyone help me please? I've been trying to figure this out for a couple of days.
Don't confuse setting a Control's Visible
property to false with making it hidden. (Yes, I'm aware of how this sounds but bear with me).
If you set the Visible property for a control to false, this means that when the html for the page is rendered on the server, the control will not produce any markup to be included. See Control.Visible at MSDN. This might be what you want, in which case Andrew Charlton's answer is what you need.
If, however, you want the <th>
and associated <td>
elements to be present in the markup for your page in the browser, but not visible i.e. hidden, then you need to use CSS to style them with display:none
e.g.
<LayoutTemplate>
<table class = "tblItemDetail" style = "color:Black;" width="100%" border="0" cellpadding="5">
<tr>
<asp:Panel ID="pnlNameHead" runat="server">
<th id="thName" runat="server" style="display:none;">Name</th>
</asp:Panel>
...
</tr>
</LayoutTemplate>
<ItemTemplate>
<tr>
<asp:Panel ID="pnlName" runat="server">
<td align="center" id="tdName" runat="server" style="display:none;">
<asp:Literal ID="lit1" runat="server" Text='<%# Eval("SupplierName") %>'></asp:Literal>
</td>
</asp:Panel>
You can't access and modify things (AFAIK) in the ItemTemplate because they aren't actual controls yet; the template is just describing what each Item will contain. You could use the ItemDataBound event to go through and hide the panel in each Item after it has been created. Something like this:
protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if(e.Item.ItemType == ListViewItemType.DataItem)
{
Panel pnl = (Panel)e.Item.FindControl("pnlName");
pnl.Visible = false;
}
}
The only other option is to build all of the templates dynamically or use UserControls:
Dynamically change GridView item template
Edit: Just saw you had the Panel around a table cell. You could remove the panel and access the cell directly in ItemDataBound:
HtmlControl td = (HtmlControl)e.Item.FindControl("tdName");
td.Visible = false;
Here are some possible reasons for the problem.
1) You can only make changes after the controls are created, typically in ItemDataBound
and LayoutCreated
events. Perhaps you are trying to do it too early?
2) There's no valid concept of wrapping a table cell in another control. I am kind of surprised this doesn't choke the parser, but maybe it works because it's just HTML. If you tried to do this with an <asp:Table>
it would not work. Anyway, it won't render valid HTML - Panel
creates a div
so the table element would be wrapped in a div. Anyway, there's no reason to do it this way; instead, just look for the element itself. The th
and td
elements are already set to runat="server"
in your example so search for them directly.
3) FindControl
is not recursive. Try using a recursive implementation. Here's an extension method I use (the last parameter is just so I can share a name with FindControl, you can change the name to something else and eliminate it if you like). This is probably why FindControl isn't returning anything, since the control you're looking for is going to be in the Controls collection of another control (tr
).
public static Control FindControl(this Control baseControl, string id, bool recurse)
{
foreach (Control ctl in baseControl.Controls)
{
if (ctl.ID==id)
{
return (ctl);
}
if (recurse && ctl.Controls.Count > 0)
{
Control subCtl = ctl.FindControl(id,recurse);
if (subCtl != null)
{
return (subCtl);
}
}
}
return (null);
}
Generally speaking, while this is doable, and I've tried it before, programatically changing the layout template is a nuisance and can result in a lot of condition handling in your code. If you cant just use CSS for some reason I'd make another template.
精彩评论