How do I position a datagridview to the searched t

2019-08-12 04:18发布

问题:

Using Windows forms and linq to Sql, I bound a datagridview to Products Table, I added to the form 1 Textbox to input the searched text. I wonder how to position the datagridview according to the text entered to find a given ProductName. Here I do not want to filter rows, I only want to reposition datagrid after each character entered, the used code:

    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;
    }

The execution of code give the next error: System.NotSupportedException was unhandled at the ligne:

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

Any idea please ?

回答1:

The MSDN documentation for BindingSource has the answer:

The Find method can only be used when the underlying list is an IBindingList with searching implemented. This method simply refers the request to the underlying list's IBindingList.Find method. For example, if the underlying data source is a DataSet, DataTable, or DataView, this method converts propertyName to a PropertyDescriptor and calls the IBindingList.Find method. The behavior of Find, such as the value returned if no matching item is found, depends on the implementation of the method in the underlying list.

When you call this method on a BindingSource whose underlying data source does not implement IBindingList then you see the exception (thrown by the default implementation of IBindingList.FindCore:

System.NotSupportedException: The specified method is not supported.

You don't show what you bind the binding source to but clearly it doesn't implement this method.

Annoyingly, BindingList<T> the recommended list type to use for your data source does not provide a FindCore implementation.

If you are using BindingList you will need to create your own custom type. Here is the code for an absolutely bare bones implementation of a BindingList that supports find:

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

    }
}

You can do lots with your own implementations of BindingList such as supporting sorting. I've left my answer as just the minimum to support the find method. Search for SortableBindingList if you want to know more.


To use this class do something like this:

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;