【问题标题】:"Select All" in CheckBoxListCheckBoxList 中的“全选”
【发布时间】:2014-01-16 14:25:55
【问题描述】:

我有一些工作代码,但我认为这不是实现目标的最佳方式。

我有一个包含 5 个项目的 CheckBoxList - 4 个单独的项目和 1 个“全选”项目。选择完全选择时,我希望其他4要为用户签出。当 Select All 被取消选择时,我希望其他 4 个为用户取消选中。

我在 StackOverflow 和 Google 上发现的一堆东西只是建议遍历 CheckBoxList.Items,但这不适用于我的情况。例如,假设用户未选中 Item #3 - 这将触发 OnSelectedIndexChanged 事件,此时我将开始循环遍历 Items。我会发现未选择“全选”项目,因此我会取消选择所有项目。因此,用户会选中第 3 项,只是为了让他们立即取消选择它。

下面是我的工作代码,但它使用了一些奇怪的功能,我无法想象这是实现我正在寻找的最佳方式。

    protected void StatusCheckBoxListChanged(object sender, System.EventArgs e)
    {
        //Crazy code I found online to determine which item triggered the event
        CheckBoxList list = (CheckBoxList)sender;
        string[] control = Request.Form.Get("__EVENTTARGET").Split('$');
        int index = control.Length - 1;
        ListItem li = (ListItem)list.Items[Int32.Parse(control[index])];

        if (li.ToString().Equals("Select All")) //If it was the "Select All" Item which triggered the event
        {
            //If it was checked, check off everything. If it was unchecked, uncheck everything.
            for(int i = 0; i < StatusCheckBoxList.Items.Count; i++)
            {
                StatusCheckBoxList.Items[i].Selected = StatusCheckBoxList.Items.FindByValue("Select All").Selected;
            }
        }
    }

【问题讨论】:

  • 你能提供CheckBoxList的标记吗?
  • 当然,虽然它是相当标准的。 &lt;asp:CheckBoxList ID="StatusCheckBoxList" OnSelectedIndexChanged="StatusCheckBoxListChanged" runat="server" AutoPostBack="True"&gt;
  • 似乎最好使用另一个CheckBox,而不是使用来自CheckBoxList的项目
  • 也许你是对的,我只是更喜欢有几个项目的布局,其中一个选择所有其他项目。无论如何,问题仍然是是否有比我提供的代码更好的方法来获取最近选择的复选框。对我来说,这是最好的选择似乎很奇怪。

标签: c# asp.net


【解决方案1】:

您可以尝试向您的页面添加字段,该字段显示全选的先前值,如下所示

bool SelectAll;

PageLoad 事件处理程序中初始化它,像这样

protected void Page_Load(object sender, EventArgs e)
{
    if(!IsPostback){
        SelectAll = StatusCheckBoxList.Items.Cast<ListItem>().FirstOrDefault(d => d.Text == "Select All" && d.Selected) != null;

    }
}

并像这样更改您的活动

protected void StatusCheckBoxListChanged(object sender, System.EventArgs e)
{
    if(SelectAll != (StatusCheckBoxList.Items.Cast<ListItem>().FirstOrDefault(d => d.Text == "Select All" && d.Selected) != null)){
        SelectAll = !SelectAll;
        foreach(var li in StatusCheckBoxList.Items){
            li.Selected = SelectAll;
        }
    }
}

注意:如果您知道具有“全选”值的项目的位置,您可以在没有 LINQ 的情况下执行类似这样的操作

“全选”为第一项时的示例

protected void Page_Load(object sender, EventArgs e)
{
    if(!IsPostback){
        SelectAll = StatusCheckBoxList.Items[0].Selected;
        foreach(var li in StatusCheckBoxList.Items){
            li.Selected = SelectAll;
        }
    }
}

并像这样更改您的活动

protected void StatusCheckBoxListChanged(object sender, System.EventArgs e)
{
    if(SelectAll != StatusCheckBoxList.Items[0].Selected){
        SelectAll = !SelectAll;
        foreach(var li in StatusCheckBoxList.Items){
            li.Selected = SelectAll;
        }
    }
}

【讨论】:

  • 这似乎是最好的解决方案,并且可以在没有我提供的“疯狂代码”的情况下完成,虽然它可以工作,但有点破解。我更喜欢你的方法!谢谢!
【解决方案2】:

我过去曾通过设置标志来解决此问题,例如

public class MyClass
{
    bool _IsReady = true;

    protected void StatusCheckBoxListChanged(object sender, System.EventArgs e)
    {
        if (!_IsReady)
        {
            return;
        }

        //Crazy code I found online to determine which item triggered the event
        CheckBoxList list = (CheckBoxList)sender;
        string[] control = Request.Form.Get("__EVENTTARGET").Split('$');
        int index = control.Length - 1;
        ListItem li = (ListItem)list.Items[Int32.Parse(control[index])];

        if (li.ToString().Equals("Select All")) //If it was the "Select All" Item which triggered the event
        {
            SetAllStatusItemsSelected(StatusCheckBoxList.Items.FindByValue("Select All").Selected);
        }
    }


    private void SetAllStatusItemsSelected(bool IsSelected)
    {
        _IsReady = false;

        //If it was checked, check off everything. If it was unchecked, uncheck everything.
        for(int i = 0; i < StatusCheckBoxList.Items.Count; i++)
        {
            StatusCheckBoxList.Items[i].Selected = StatusCheckBoxList.Items.FindByValue("Select All").Selected;
        }

        _IsReady = true;
    }

}

我很想知道是否有更优雅的方式。

【讨论】:

  • 我对你的代码有点困惑 - 它遍历每个项目并将它们的 Selected 值设置为与“全选”项目相同的值(无论“全选”项目是否最近检查的)。对吗?
  • 当你打电话给StatusCheckBoxListChanged时,似乎_IsReady总是true
  • 正确 - 但只要调用处理“全选”功能的逻辑并调用 SetAllStatusItemsSelected(),则标志设置为 false。因此,当 CheckBoxList 中的每个项目都被重置时,将调用 OnSelectedIndexChanged 事件,但 _IsReady 将为 false,因此处理程序中的其余代码将不会运行,直到 CheckBoxList 中的所有项目都被重置。
  • 您说“我过去曾解决过这个问题”,但随后在您的答案中包含了我的“疯狂代码”-您的代码如何改进我的代码? (我不是要指责,我真的不确定)
  • 嗯...看来我错过了杰克说代码工作的部分。我可能正在尝试解决错误的问题!我在此撤回我的回答 - 向所有人道歉。
【解决方案3】:

这是我一直解决这个问题的方法

        protected void CheckBoxList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        CheckBoxList lstBx = (CheckBoxList)sender;

        List<ListItem> list = lstBx.Items.Cast<ListItem>().ToList();
        string[] control = Request.Form.Get("__EVENTTARGET").Split('$');
        int index = Convert.ToInt32(control[control.Length - 1]);

        ListItem selectAllControl = list.FirstOrDefault(x => x.Text == "Select All");
        ListItem selectAll = list.FirstOrDefault(x => x.Selected && x.Text == "Select All");

        if (index == 0)
        {               
            if (selectAll != null)
            {
                foreach (var item in list)
                {
                    item.Selected = true;
                }
            }
        }
        else
        {
            if (selectAllControl != null)
            {
                selectAllControl.Selected = false;
            }
        }

    }

【讨论】:

  • @Jake,你在说什么不幸。?此代码有效。
  • @LawrenceThurman,看来你和我一样,错过了第 1 段和第 4 段的开头:“我有一些工作代码......”和“下面是我的工作代码......”。它有效,但看起来并不优雅。
  • @MarkHone 我确实看到了 cmets。这是一个更干净的代码。对 Jake 的一个问题 - 我没有在您的代码中看到当用户选择说您的第三项时您取消选择全选。
  • 很遗憾,因为您的代码没有对我的代码进行任何有意义的更改。它包括我标记为“疯狂代码”的内容,以便找到最近更改的项目。你说它是“更简洁的代码”,但我的代码要少得多才能达到相同的效果。至于“当用户选择您的第三个项目时您取消选择全选”,您是对的,我在我提供的代码中没有这样做,如果用户手动选择每个项目,我也不会选择全选。我在我的个人代码中这样做了,但我没有在这里发布它,因为这不是真正的问题。
  • @Jake 您的解决方案和我的解决方案允许开发人员做的一件事是重用所有 checkboxList 控件的代码。如果您使用 flag 方法,则页面上的每个复选框列表控件都需要一个标志。虽然你可能只有一个,但在这种情况下你很好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多