【问题标题】:How do I position a datagridview to the searched text input如何将 datagridview 定位到搜索到的文本输入
【发布时间】:2012-07-26 08:49:33
【问题描述】:

使用 Windows 窗体和 linq to Sql,我将一个 datagridview 绑定到 Products Table,我添加到窗体 1 文本框以输入搜索到的文本。 我想知道如何根据输入的文本定位 datagridview 以查找给定的 ProductName。 这里我不想过滤行,我只想在输入每个字符后重新定位datagrid,使用的代码:

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        var searchValue = textBox1.Text.Trim().ToUpper();
        var qry = (from p in dc.Products
                   where p.ProductName.ToUpper().StartsWith(searchValue)
                   select p).ToList();
        int itemFound = productBindingSource.Find("ProductName", searchValue);
        productBindingSource.Position = itemFound;
    }

代码的执行给出了下一个错误:System.NotSupportedException was unhandled at the ligne:

int itemFound = productBindingSource.Find("ProductName", searchValue);

有什么想法吗?

【问题讨论】:

  • datagridview 中是否有多个项目以输入的文本开头?这可能会导致异常。此外,“查找”功能是否只查看列是否以提供的值开头?
  • 在表单加载事件数据网格中填充了 Products 表的全部内容。
  • 对,但是 Find 会返回多个结果吗?
  • @Chris,在出现错误消息后,datagridview 中的所有产品都没有变化,因为无法识别整数 itemFound

标签: winforms c#-4.0 linq-to-sql datagridview find


【解决方案1】:

MSDN documentation for BindingSource 有答案:

Find 方法只能在底层列表是 实现了搜索的 IBindingList。这种方法只是指 请求基础列表的 IBindingList.Find 方法。为了 例如,如果基础数据源是 DataSet、DataTable 或 DataView,该方法将propertyName转换为PropertyDescriptor 并调用 IBindingList.Find 方法。 Find 的行为,例如 如果没有找到匹配项,则返回的值取决于 底层列表中方法的实现。

当您在底层数据源未实现 IBindingList 的 BindingSource 上调用此方法时,您会看到异常(由 IBindingList.FindCore 的默认实现抛出:

System.NotSupportedException:不支持指定的方法。

您没有显示绑定源绑定到什么,但显然它没有实现此方法。

令人讨厌的是,BindingList<T> 用于您的数据源的推荐 列表类型不提供FindCore 实现。

如果您使用 BindingList,您将需要创建自己的自定义类型。以下是支持 find 的 BindingList 的绝对简单实现的代码:

public class FindableBindingList<T> : BindingList<T>
{

    public FindableBindingList()
        : base()
    {
    }

    public FindableBindingList(List<T> list)
        : base(list)
    {
    }

    protected override int FindCore(PropertyDescriptor property, object key)
    {
        for (int i = 0; i < Count; i++)
        {
            T item = this[i];
            if (property.GetValue(item).Equals(key))
            {
                return i;
            }
        }
        return -1; // Not found

    }
}

您可以使用自己的 BindingList 实现做很多事情,例如支持排序。我将我的答案作为支持 find 方法的最低要求。如果您想了解更多信息,请搜索 SortableBindingList。


要使用此类,请执行以下操作:

var qry = (from p in dc.Products
               where p.ProductName.ToUpper().StartsWith(searchValue)
               select p).ToList();    

FindableBindingList<YourType> list = new FindableBindingList<YourType>(qry);

dataGridView1.DataSource = list;

【讨论】:

  • 谢谢你的回复,请问有没有最简单的替代方法来达到同样的目的,或者你可以解释更多如何使用你的代码。
  • 这一切都取决于 - 因为你没有说你的数据源是什么,所以很难更准确。有诸如 DataTable 之类的自动支持 Find 的源,但如果你不能使用其中之一(我通常避免使用它们),最好是实现你自己的 BindingList。我会在一分钟内给出一个更完整的例子。顺便说一句,如果你直接使用 Linq-to-sql 来填充你的网格,你会遇到麻烦,因为这通常会给你只读匿名类型,有利于阅读,很不利于写作。
  • 非常感谢您的努力。我的网格当前绑定到绑定到由 Linq to Sql 模型提供的 Products 类的 BindingSource 控件,通常我避免使用 Dataset 作为数据源,过去我更喜欢使用实体框架,然后我注意到使用 Linq to Sql 给我更好的性能和更少的复杂性,所以我在我的项目中采用了 Linq to SQL Classes。由于 BindingList 是我以前从未了解过的东西,所以我会花一些时间来阅读它,然后再回来尝试您的建议并反馈我的反馈。再次感谢您的帮助。
  • @AlphaBird 那是你的问题 - 你来自 Linq-to-sql 的列表没有实现 Find。可能最简单的方法是从 linq 中获取您的列表并将其传递到启用查找的绑定列表中。
猜你喜欢
  • 1970-01-01
  • 2016-10-04
  • 2013-11-08
  • 2015-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多