Question

I know you can put <% if %> statements in the ItemTemplate to hide controls but the column is still there. You cannot put <% %> statements into the LayoutTemplate which is where the column headings are declared, hence the problem. Does anyone know of a better way?

Was it helpful?

Solution

Here's another solution that I just did, seeing that I understand what you want to do:

Here's your ASCX / ASPX

    <asp:ListView ID="ListView1" runat="server" DataSourceID="MyDataSource" ItemPlaceholderID="itemPlaceHolder" OnDataBound="ListView1_DataBound">
        <LayoutTemplate>
            <table border="1">
                <tr>
                    <td>Name</td>
                    <td>Age</td>
                    <td runat="server" id="tdIsSuperCool">IsSuperCool</td>
                </tr>
                <asp:PlaceHolder ID="itemPlaceHolder" runat="server" />
            </table>
        </LayoutTemplate>
        <ItemTemplate>
            <tr>
                <td><%# Eval("Name") %></td>
                <td><%# Eval("Age") %></td>
                <td runat="server" id="myCol" visible='<%# (bool)Eval("IsSuperCool") %>'>true</td>
            </tr>
        </ItemTemplate>
    </asp:ListView>
    <asp:ObjectDataSource 
        ID="MyDataSource" 
        runat="server" 
        DataObjectTypeName="BusinessLogicLayer.Thing" 
        SelectMethod="SelectThings"
        TypeName="BusinessLogicLayer.MyObjectDataSource" />

Here's the code behind

/// <summary>
/// Handles the DataBound event of the ListView1 control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected void ListView1_DataBound(object sender, EventArgs e)
{
    ListView1.FindControl("tdIsSuperCool").Visible = false;
}

Do whatever you want in the databound. Because the column is now runat server, and you're handling the DataBound of the control, when you do ListView1.FindControl("tdIsSuperCool") you're in the Layout template so that works like a champ.

Put whatever business logic that you want to control the visibility of the td and you're good.

OTHER TIPS

Try Using a Panel and you can turn it on / Off

 foreach (ListViewItem item in ListView1.Items)
 {
     ((Panel)item.FindControl("myPanel")).Visible= False;
 }

The ListView gives you full control about how the data is rendered to the client. You specify the Layout Template, and give a placeholder which will be where each item is injected.

The output of the below will give you a table, and each item will be a new TR.

Notice the use of runat='server' and visible ='<%# %>'

<asp:ListView ID="ListView1" runat="server" DataSourceID="MyDataSource" ItemPlaceholderID="itemPlaceHolder">
    <LayoutTemplate>
        <table>
            <asp:PlaceHolder ID="itemPlaceHolder" runat="server" />
        </table>
    </LayoutTemplate>
    <ItemTemplate>
        <tr>
            <td runat="server" id="myCol" visible='<%# (bool)Eval("IsSuperCool") %>'>
                <%# Eval("SuperCoolIcon") %>
            </td>
            <td>
                <%# Eval("Name") %>
            </td>
            <td>
                <%# Eval("Age") %>
            </td>
        </tr>
    </ItemTemplate>
</asp:ListView>

I know it's a very old question, but I'm actually having to do this and think I found a fairly nice way to do it through jquery and css.

Add the following to the header:

<script type="text/javascript" src="Scripts/jquery-1.7.1.min.js" ></script>
  <style>
    .hide {
      display:none;
    }
    .show {
      display:block;
    }
  </style>

For all columns that you want to hide, add a custom property to the td/th.

<th runat="server" data-prop='authcheck'  id="tdcommentsHeader"  >Comments</th>

I'm advising to use a custom property because, long story short, it can kill a bunch of birds with one stone. You won't even need to change the value for each column, as you would if we based this on the id property.

Next, ensure you have a hidden field that tells lets you know whether or not to hide the column. This can be an asp:HiddenField or any other so long as it's on the form.

<asp:HiddenField runat="server" ID="IsAuthorized" Value="false" />

Finally, at the bottom of the page, do:

        <script type="text/javascript">
          $(document).ready(function () {
            var isauth = $("[id='IsAuthorized']").val();
              if (isauth==="false") {
              $("[data-prop='authcheck']").addClass('hide');
              //$("[id*='tdcomments']").addClass('hide'); 
            }
          });
      </script>

You can always set the column width to 0 (zero) if you don't find a better way.

The listview doesn't really have a concept of 'column' since it is intended just to be, well, a list.

I'm going to assume that you are using databinding to attach a list of 'somethings' to the ListView. If that is the case then you will just have a list of items and the html in the LayoutTemplate will decide on just how those items are displayed. If you are then talking about creating a table-style array of columns and rows then maybe a DataGrid would be a better choice since this gives much more programmatic control of specific columns.

It may be that you are hoping to create the table layout entirely through CSS, which is an admirable decision if it is purely for layout purposes. However, your requirement to specifically hide one column indicates to me that a table is better placed to suit your needs. It's fine to use tables for tabular data...IMHO...

If you really do need to use a ListView then you could always try binding against something in your data which determines whether an element should be shown or not, e.g.:

style='display: <%#Eval("DisplayStyle") %>;'

Place this code within the html element that you want to control (in the LayoutTemplate). Then in the object you are binding to you would need a property 'DisplayStyle' which was either set to 'block' or 'none'.

To access the layout template column header text, I made them labels in the template, and did a findcontrol in the prerender of the listview, then made the labels blank text if the column should be "off". This might not work for your intentions, but for me I still wanted the column space to be used, just appear blank.

The further you go try to make a listview bend over backwards, the more you will wish you used a grid instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top