首页 > 解决方案 > 突出显示 ListView 行而不重新绑定或将样式应用于该行

问题描述

典型的列表视图。

    <asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" OnSelectedIndexChanging="ListView1_SelectedIndexChanging" 
        OnSelectedIndexChanged="ListView1_SelectedIndexChanged">
        <ItemTemplate>
            <tr style="">
                <td>
                    <asp:Label ID="FirstNameLabel" runat="server" Text='<%# Eval("FirstName") %>' />
                </td>
                <td>
                    <asp:Label ID="LastNameLabel" runat="server" Text='<%# Eval("LastName") %>' />
                </td>
                <td>
                    <asp:Label ID="HotelNameLabel" runat="server" Text='<%# Eval("HotelName") %>' />
                </td>
                <td>
                    <asp:Label ID="CityLabel" runat="server" Text='<%# Eval("City") %>' />
                </td>
                <td>
                    <asp:Button ID="cmdLstSel" runat="server" Text="View" CssClass="btn" 
                        CommandName="Select"/>
                </td>
            </tr>
        </ItemTemplate>
        <SelectedItemTemplate>
            <tr style="" class="alert-info">
                <td>
                    <asp:Label ID="FirstNameLabel" runat="server" Text='<%# Eval("FirstName") %>' />
                </td>
                <td>
                    <asp:Label ID="LastNameLabel" runat="server" Text='<%# Eval("LastName") %>' />
                </td>
                <td>
                    <asp:Label ID="HotelNameLabel" runat="server" Text='<%# Eval("HotelName") %>' />
                </td>
                <td>
                    <asp:Label ID="CityLabel" runat="server" Text='<%# Eval("City") %>' />
                </td>
                <td>
                    <asp:Button ID="cmdLstSel" runat="server" Text="View" CssClass="btn" OnClick="cmdLstSel_Click" />
                </td>
            </tr>

        </SelectedItemTemplate>
        <LayoutTemplate>
            <table runat="server">
                <tr runat="server">
                    <td runat="server">
                        <table id="itemPlaceholderContainer" runat="server" border="0" style="">
                            <tr runat="server" style="">
                                <th runat="server">FirstName</th>
                                <th runat="server">LastName</th>
                                <th runat="server">HotelName</th>
                                <th runat="server">City</th>
                                <th runat="server">View</th>
                            </tr>
                            <tr id="itemPlaceholder" runat="server">
                            </tr>
                        </table>
                    </td>
                </tr>
                <tr runat="server">
                    <td runat="server" style="">
                        <asp:DataPager ID="DataPager1" runat="server">
                            <Fields>
                                <asp:NextPreviousPagerField ButtonType="Button" ShowFirstPageButton="True" ShowLastPageButton="True" />
                            </Fields>
                        </asp:DataPager>
                    </td>
                </tr>
            </table>
        </LayoutTemplate>
    </asp:ListView>

所以我们可以突出显示点击的行:

   protected void ListView1_SelectedIndexChanging(object sender, ListViewSelectEventArgs e)
    {
        
    }

    protected void ListView1_SelectedIndexChanged(object sender, EventArgs e)
    {
        GPayments.DataSource = MyRst("SELECT * FROM HotelPayments WHERE Hotel_ID = " + hID);
        GPayments.DataBind();
    }

现在,如果我省略重新绑定,那么该行当然会突出显示,但当然是“上一个”行突出显示。

如果我可以设置 ONE 行的类,那么我可以转储所选项目模板。

您可以在 GridView 中轻松地做到这一点,我经常这样做:

    Dim gRow As GridViewRow = -- get any row

    gRow.CssClass = " alert-info"

但是,我想对 listView 做同样的事情。当我为 GridView 执行上述操作时,我不需要或不必费心重新绑定,我什至也不需要选定的模板。

所以左边是一个网格视图,我们得到这个:

在此处输入图像描述

但是,我想用 listview 来做到这一点。(并且无需重新绑定)。

任何简单的方法来突出显示 ListView 中的一行而不重新绑定?

标签: c#asp.netvb.netlistviewwebforms

解决方案


好的,有点谷歌搜索,解决方案变得非常简单。

这里的目标是单击一行 - 突出显示该行。

当然,要包含选定的行模板需要做太多的工作。

添加 3 行代码来执行此操作是一个更好的权衡。

所以,假设我们有这个标记:

    <asp:ListView ID="ListView1" runat="server" DataKeyNames="ID" 
        OnSelectedIndexChanged="ListView1_SelectedIndexChanged" OnSelectedIndexChanging="ListView1_SelectedIndexChanging" >
        <ItemTemplate>
            <tr id="mytr" runat="server">
                <td><asp:Label ID="FirstNameLabel" runat="server" Text='<%# Eval("FirstName") %>' /></td>
                <td><asp:Label ID="LastNameLabel" runat="server" Text='<%# Eval("LastName") %>' /></td>
                <td><asp:Label ID="HotelNameLabel" runat="server" Text='<%# Eval("HotelName") %>' /></td>
                <td><asp:Label ID="CityLabel" runat="server" Text='<%# Eval("City") %>' /></td>
                <td>
                    <asp:Button ID="cmdLstSel" runat="server" Text="View" CssClass="btn" 
                        CommandName="Select" OnClick="cmdLstSel_Click"/>
                </td>
            </tr>
        </ItemTemplate>
        <LayoutTemplate>
                <table id="itemPlaceholderContainer" runat="server" border="0" class="table table-hover" style="">
                    <tr runat="server" style="">
                        <th runat="server">FirstName</th>
                        <th runat="server">LastName</th>
                        <th runat="server">HotelName</th>
                        <th runat="server">City</th>
                        <th runat="server">View</th>
                    </tr>
                    <tr id="itemPlaceholder" runat="server">
                    </tr>
                </table>
        </LayoutTemplate>
    </asp:ListView>

好的,我们要填写的代码是这样的:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
            LoadView();
    }
}
void LoadView()
    {
        ListView1.DataSource = MyRst("SELECT TOP 12 * FROM tblHotels ORDER BY HotelName");
        ListView1.DataBind();
    }

输出:

在此处输入图像描述

好的,那么对于行点击?好吧,我们不必使用已更改的选定索引,但是,为此我们将(因此 CommandName="Select" 是触发索引更改事件的原因)。

但是,我想要一个简单的按钮单击,并带有一些代码(显示详细信息部分)。

所以,我们的按钮点击是这样的:

protected void cmdLstSel_Click(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        ListViewDataItem gRow = (ListViewDataItem)btn.Parent.Parent.Parent;

        int hID = (int)ListView1.DataKeys[gRow.DisplayIndex]["ID"];
        GHotelOptions.DataSource = MyRst("SELECT * FROM HotelOptions WHERE Hotel_ID = " + hID);
        GHotelOptions.DataBind();

        GPayments.DataSource = MyRst("SELECT * FROM HotelPayments WHERE Hotel_ID = " + hID);
        GPayments.DataBind();

    }

上面将填充子表。请注意获取行的酷技巧 - 我不打扰 listview 事件模型!

现在为行突出显示。

诀窍是向 tr 行添加一个“id”,如下所示:

 <ItemTemplate>
      <tr id="mytr" runat="server">

所以,我们现在可以拿起 tr 元素。

所以在 lv 索引改变时,我们这样做:

    protected void ListView1_SelectedIndexChanged(object sender, EventArgs e)
    {

        ListViewItem gRow = (ListViewItem)ListView1.Items[ListView1.SelectedIndex];
        if ( (ViewState["MySel"] != null) && ((int)ViewState["MySel"] != gRow.DataItemIndex) )
        {
            ListViewItem gLast = ListView1.Items[(int)ViewState["MySel"]];
            HtmlTableRow hTRL = (HtmlTableRow)gLast.FindControl("mytr");
            hTRL.Attributes.Add("class", "");
        }
        HtmlTableRow hTR = (HtmlTableRow)gRow.FindControl("mytr");
        hTR.Attributes.Add("class", "alert-info");

        ViewState["MySel"] = gRow.DataItemIndex;
   }

所以,我确实使用了行状态,但这让我取消突出显示 + 突出显示,并且我不必重新绑定网格。

我刚刚选择了一个不错的引导类——它甚至可以“反转”文本——非常好。

所以现在我们得到了这个: 在此处输入图像描述

所以这确实花费了大约 4-5 条额外的线路。但是,我们将其换成在 lv 中没有选定的模板(这对于维护行布局来说太过分了,然后必须为选定的模板维护相同的布局。更糟糕的是,您仍然必须为突出显示的行重新绑定点击显示。这样,我们没有。

我还使用“助手”例程来获取数据表,就是这样:

public DataTable MyRst(string strSQL)
{
    DataTable rstData =  new DataTable();
    using (SqlCommand cmdSQL = new SqlCommand(strSQL,
        new SqlConnection(Properties.Settings.Default.TEST3)))
    {
        cmdSQL.Connection.Open();
        rstData.Load(cmdSQL.ExecuteReader());
    }
    return rstData;
}

在一天结束时,我们现在可以突出显示该行,只需单击一下,我们甚至可以将选定的索引更改代码移动到我们的按钮代码,甚至不使用 lv 索引和内置事件。


推荐阅读