将项目的检查状态保留在搜索C#Winforms的复选框列表中 - c#

所以我正在使用基于文本框的筛选器,使用c#在winforms中的Checked List Box中检查一堆项目。

到目前为止,我有以下代码:

List<string> liscollection = new List<string>();
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(textBox1.Text) == false)
            {
                checkedListBox1.Items.Clear();

                foreach (string str in liscollection)
                {
                    if (str.Contains(textBox1.Text, StringComparison.OrdinalIgnoreCase))
                    {
                        checkedListBox1.Items.Add(str);
                    }
                }
            }
            else if (textBox1.Text == "")
            {
                checkedListBox1.Items.Clear();
                foreach (string str in liscollection)
                {
                    checkedListBox1.Items.Add(str);
                }
            }
        }

当我在TextBox1中输入文本时,一切正常,所有不包含输入文本的项目都消失了。
问题涉及到每个项目的检查状态。每次checkedListBox1.Items.Clear();被调用时,检查状态也将被清除。

有没有一种方法可以使过滤器保持工作状态,但又不能清除项目的已检查状态?

我已经寻找了一段时间,对此一无所获,我是一个初学者,无法独自提出解决方案。

非常感谢您抽出宝贵的时间!

请问我的英语不是我的母语:)

参考方案

CheckListBox.Items的类型为ObjectCollection,这意味着它将接受任何object,而不仅仅是string。默认情况下,CheckedListBox将显示ToString的结果作为项目的文本。

这意味着您可以编写一个class来表示存储在CheckedListBox中的项目,这些项目跟踪其自己的CheckedState属性,然后覆盖ToString方法,以便显示所需的文本。

// CheckedListBoxItem.cs
public class CheckedListBoxItem
{
    /// <summary>
    /// The item's text - what will be displayed in the CheckedListBox.
    /// </summary>
    public string Text { get; set; }

    /// <summary>
    /// The item's check state.
    /// </summary>
    public CheckState CheckState { get; set; } = CheckState.Unchecked;

    /// <summary>
    /// Whether the item is checked or not.
    /// </summary>
    public bool Checked
    {
        get
        {
            return (CheckState == CheckState.Checked || CheckState == CheckState.Indeterminate);
        }
        set
        {
            if (value)
            {
                CheckState = CheckState.Checked;
            }
            else
            {
                CheckState = CheckState.Unchecked;
            }
        }
    }

    public bool Contains(string str, StringComparison comparison)
    {
        return Text.IndexOf(str, comparison) >= 0;
    }

    public override string ToString()
    {
        return Text;
    }
}

CheckedListBoxItem.Checked的行为基于将CheckedListBox.GetItemChecked视为已选中的CheckState.Interetminate和将CheckedListBox.SetItemChecked视为true并将CheckState.Checked视为falseCheckState.Unchecked

然后,在您的Form中,将lstcollection的类型更改为List<CheckedListBoxItem>,并将每个项目的Text属性设置为您现在拥有的字符串。

CheckedListBox没有任何方式绑定每个项目的CheckState,因此您必须自己进行管理。幸运的是,有一个CheckedListBox.ItemChecked事件将在项目的选中状态更改时触发。因此,您可以使用以下功能处理事件:

private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
{
    // Since each item in the CheckedListBox is of type CheckedListBoxItem, we can
    // just cast to that type...
    CheckedListBoxItem item = checkedListBox1.Items[e.Index] as CheckedListBoxItem;

    // Then set the checked state to the new value.
    item.CheckState = e.NewValue;
}

过滤器功能在很大程度上保持不变,但是当您将项目添加到CheckedListBox时,还必须通过CheckedState

private List<CheckedListBoxItem> liscollection;

private void textBox1_TextChanged(object sender, EventArgs e)
{
    checkedListBox1.Items.Clear();
    if (string.IsNullOrEmpty(textBox1.Text) == false)
    {
        foreach (var item in liscollection)
        {
            if (item.Contains(textBox1.Text, StringComparison.OrdinalIgnoreCase))
            {
                checkedListBox1.Items.Add(item, item.CheckState);
            }
        }
    }
    else
    {
        foreach (var item in liscollection)
        {
            checkedListBox1.Items.Add(item, item.CheckState);
        }
    }
}

编辑

对于这种情况,我不会在设计时将项目添加到checkedListBox1。我会在运行时将它们添加到liscollection,然后将liscollection添加到checkedListBox1.Items

public class YourForm : Form
{
    public YourForm()
    {
        InitializeComponent();

        // You would add one item to liscollection for each item that you have in the checkedListBox1's designer and set the Text to whatever the item is now...
        liscollection = new List<CheckedListBoxItem>
        {
           new CheckedListBoxItem { Text = "The" },
           new CheckedListBoxItem { Text = "needs" },
           new CheckedListBoxItem { Text = "of" },
           new CheckedListBoxItem { Text = "the" },
           new CheckedListBoxItem { Text = "many" },
           new CheckedListBoxItem { Text = "outweigh" },
           new CheckedListBoxItem { Text = "the" },
           new CheckedListBoxItem { Text = "needs" },
           new CheckedListBoxItem { Text = "of" },
           new CheckedListBoxItem { Text = "the" },
           new CheckedListBoxItem { Text = "few" },
        };
        checkedListBox1.Items.AddRange(liscollection.ToArray());
    }
}

如果您真的希望从设计器中填充checkedListBox1,也可以这样做。您只需在填充checkedListBox1.Items.Clear()之后且在调用liscollection之前调用checkedListBox1.Items.AddRange(...)

public class YourForm : Form
{
    public YourForm()
    {
        InitializeComponent();

        liscollection = new List<CheckedListBoxItem>();
        foreach(string str in checkedListBox1.Items)
        {
            liscollection.Add(new CheckedListBoxItem { Text = str });
        }
        checkedListBox1.Items.Clear();
        checkedListBox1.Items.AddRange(liscollection.ToArray());
    }
}

重要行是checkedListBox1.Items.AddRange(liscollection.ToArray())。您希望ItemsCheckedListBoxItem的实例,这样在ItemCheck事件中,您可以将项目强制转换为CheckedListBoxItem的实例。通过从设计器填充checkedListBox1,您仅用string填充了它,因此,当您尝试在CheckedListBoxItem事件中强制转换为ItemCheck时,它将失败。这就是为什么要获取该NullReferenceException的原因。

当回复有时是一个对象有时是一个数组时,如何在使用改造时解析JSON回复? - java

我正在使用Retrofit来获取JSON答复。这是我实施的一部分-@GET("/api/report/list") Observable<Bills> listBill(@Query("employee_id") String employeeID); 而条例草案类是-public static class…

如何使用%s在python中使用Selenium变量构建xpath表达式 - python

我正在尝试使用硒根据调用时传递给函数的变量来定位和选择某个元素。我以为,有了一个好的ol,这将足够简单:show = browser.find_element_by_xpath("//*[contains(text(), '%s')]" % eventName) 但是,我收到错误:selenium.common.exc…

使用Json.NET反序列化复杂对象 - c#

我需要反序列化从grogle maps api返回的json:{ "destination_addresses": [ "Via Medaglie D'Oro, 10, 47121 Forlì FC, Italia", "Via Torino, 20123 Milano, Italia",…

Mongo汇总 - javascript

我的收藏中有以下文件{ "_id": ObjectId("54490b8104f7142f22ecc97f"), "title": "Sample1", "slug": "samplenews", "cat": …

如何在Wiremock中为JUNIT匹配精确的json - java

我正在使用Wiremock在Spring启动应用程序中模拟Junit的REST服务。我的问题是,我无法匹配多个匹配模式。 Junit.javaStringValuePattern pattern = WireMock.matching(".*"); givenThat(post(urlEqualTo("/softwares�…