如何通过文本框搜索列表框

问题描述 投票:0回答:1

我尝试搜索列表框,但它只搜索第一列,其他列好像不存在。列表框中的数据由空格分隔,它是 4 列数据。

这是我尝试过的

listBox1.ClearSelected();
string data = txtSearch.Text;

if (!string.IsNullOrEmpty(data))
{
    int index = listBox1.FindString(data);
    if (index >= 0)
    {
        listBox1.SetSelected(index, false);
        MessageBox.Show("string" + data + "found at index " + index);
        txtSearch.Clear();
    }
    else
    {
        MessageBox.Show("Search string did not match any item");
        txtSearch.Clear();
    }
}
c# winforms
1个回答
0
投票

您忘记写下如何填写列表框。通常有两种方法来填充列表框:

您没有说明您要显示什么类型的内容,让我们假设您显示产品的一些属性:Id、Name、Price。您希望将它们显示在列表框中整齐的列中。

class Product
{
    public int Id {get; set;}
    public string Name {get; set;}
    public decimal Price {get; set;}

    ... // other properties
}

某个地方有一个方法可以获取要在列表框中显示的产品:

IEnumerable<Product> GetProductsToDisplay() {...}

如果您使用数据源的解决方案

每当您想在 winforms 控件中显示项目序列时,这是首选方法,因为使用此方法,您不会在显示的产品描述中思考,而是在

DisplayedProduct
的对象中思考。如果操作员在列表框中选择一个字符串,则他在内部选择了一个产品。软件更容易确定选择哪个产品。

除了更容易访问产品之外,使用数据源还可以将显示的项目与用于显示它的控件分离。如果稍后您决定要在 DataGridView 中显示产品序列,则更改很小。如果您想在更奇特的控件(如图表)中显示产品(的价格),您甚至可以重用这些类。

class DisplayedProduct
{
    // ths format string to convert the Product into its displayformat
    private const string descriptionFormat = ...;

    public Product Product {get; set;}

    public string Description => String.Format(descriptionFormat,
        this.Product.Id,
        this.Product.Name,
        this.Product.Price);
}

在表单的构造函数中,您使用属性 ListControl.DisplayMember 来定义用于显示的属性:

void MyForm()
{
    InitializeComponent();

    this.myListbox.DisplayMember = nameof(DisplayedProduct.Description);
}

您也可以使用 Visual Studio Designer 来执行此操作,但此方法的优点是,如果出现输入错误,编译器会抱怨。

现在展示产品:

IEnumerable<Product> DisplayedProducts
{
    get => this.myListBox.DataSource
        .Select(displayedProduct => displayedProduct.Product);
    set => this.myListBox.DataSource = value
        .Select(product => new DisplayedProduct {Product = product))
        .ToList();
}

因此,要显示您的产品,您需要提供一系列产品,set 属性会将其转换为

list<DisplayedProducts>
,并将结果放入 ListBox 的数据源中。

要获取 DisplayedProducts,需要从数据源中获取

list<DisplayedProducts>
。从该列表中的每个元素中,获取属性 Product。

展示您的产品只需一行:

this.DisplayedProducts = this.GetProductsToDisplay();

创建方法 DisplayedProducts 后,可以轻松搜索名称中包含特定文本的产品:

const string textToSearch = "Hammer"

// find all Hammers:
IEnumerable<Product> hammers = this.DisplayedProducts
    .Where(product.Name.Contains(textToSearch);

// find the most expensive Hammer
Product mostExpensiveHammer = this.DisplayedProducts
    .Where(product.Name.Contains(textToSearch)
    .OrderByDescending(product => product.Price)
    .FirstOrDefault();

我认为使用数据源可以轻松回答您的问题。

因为您将产品与其显示方式分离,所以很容易

  • 将您的产品重复用于其他用途
  • 对产品进行单元测试
  • 更改产品,而无需更改ListBox,例如,您可以添加属性ProductType或Location,而无需更改ListBox。
  • 无需更改产品即可改变您展示产品的方式。可以轻松添加或删除部分显示文本,而无需更改处理产品的方法,例如搜索产品。

所以我的建议是使用数据源在列表框中显示产品

为了完整起见,以下属性可能会很方便:

Product SelectedProduct => (DisplayedProduct)(this.SelectedValue)?.Product;



   

如果您使用 ListBox.Items 的解决方案

如果您使用 ListBox.Items 来显示产品,您的表单将具有如下方法:

// Formats the product into ListBox description, using columns
string ProductToListBoxDescription(Product product)
{
    const string listBoxProductDescriptionFormat = ...;
    return String.Format(listBoxProductDescriptionFormat,
        product.Id,
        product.Name,
        product.Price);
}

void DisplayProductDescriptions(IEnumerable<string> products)
{
    this.myListBox.Items.Clear;
    foreach (Product product in Pro
    this.myListBox.Items.AddRange(products.ToArray());
}

要获取显示的产品:

IEnumerable<string> DisplayedProductDescriptions => this.myListBox.Items.Cast<string>();

这个缺点是,您丢失了获取的字符串是产品的信息。当然,您可以假设字符串包含产品:

const string textToSearch= "Hammer"

string foundHammer = this.DisplayedProductDescriptions
    .Where(description => discription.Contains(textToSearch))
    .FirstOrDefault();

首先,你的结果仍然是一个字符串。其次,如果您尝试搜索“2.0”,例如尝试查找版本号为 2.0 的所有产品,该怎么办?您还会发现价格为 €2.0 和 €42.0 等的产品说明。

因此,为了正确使用,您需要一种将字符串转换回产品的方法

Product DescriptionToProduct(string productDescription)
{
    ... // TODO implement. Depends on the columns in your listBox
}

除了如果使用属性 Items 显示的产品描述比使用属性 DataSource 时大得多之外,此方法还会删除列表框中显示的项目是产品的信息,这需要额外的代码将字符串转换回来到产品。

所以我的建议是:虽然属性 Items 有效,但坚持使用属性 DataSource。

© www.soinside.com 2019 - 2024. All rights reserved.