How to move by code the BindingSource to a specific record

Viewed 29149

Using datagridview bound to BindingSource control bound to a LINQ to SQL class, I wonder how to position the bindingSource to a specific record, that is, when I type a Product name in a textbox, the bindingsource should move to that specific product. Here is my code:

In my form FrmFind:

    NorthwindDataContext dc;
    private void FrmFind_Load(object sender, EventArgs e)
    {
        dc = new NorthwindDataContext();

        var qry = (from p in dc.Products
                   select p).ToList();

        FindAbleBindingList<Product> list = new FindAbleBindingList<Product>(qry);

        productBindingSource.DataSource = list.OrderBy(o => o.ProductName);
    }

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        TextBox tb = sender as TextBox;

        int index = productBindingSource.Find("ProductName", tb.Text);

        if (index >= 0)
        {
            productBindingSource.Position = index;
        }
    }

In the program class:

    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))
                if (property.GetValue(item).ToString().StartsWith(key.ToString()))
                {
                    return i;
                }
            }
            return -1; // Not found
        }
    }

How can I implement the find method to make it work?

3 Answers

I took a different approach. I figured, programmatically, every record must be checked until a match is found, so I just iterated using the MoveNext method until I found a match. Unsure if the starting position would be the First record or not, so I used the MoveFirst method to ensure that is was.

There is one assumption, and that is that what you are searching for is unique in that column. In my case, I was looking to match an Identity integer.

int seekID;        
this.EntityTableBindingSource.MoveFirst();
if (seekID > 0)
{
     foreach (EntityTable sd in EntityTableBindingSource)
     {
         if (sd.ID != seekID)
         {
             this.t_EntityTableBindingSource.MoveNext();
         }
         else
         {
             break;
         }
      }
 } 

I didn't really care for either answer provided. Here is what I came up with for my problem:

// Create a list of items in the BindingSource and use labda to find your row:
var QuickAccessCode = customerListBindingSource.List.OfType<CustomerList>()
    .ToList().Find(f => f.QuickAccessCode == txtQAC.Text);

// Then use indexOf to find the object in your bindingSource:
var pos = customerListBindingSource.IndexOf(QuickAccessCode);
if (pos < 0)
{
    MessageBox.Show("Could not find " + txtQAC.Text);
}
else
{
    mainFrm.customerListBindingSource.Position = pos;
}
Related