Winforms 如何通过代码将BindingSource移动到特定记录

Winforms 如何通过代码将BindingSource移动到特定记录,winforms,c#-4.0,linq-to-sql,datagridview,bindingsource,Winforms,C# 4.0,Linq To Sql,Datagridview,Bindingsource,使用绑定到绑定到类的BindingSource控件的datagridview,我想知道如何将BindingSource定位到特定记录,也就是说,当我在文本框中键入产品名称时,BindingSource应该移动到该特定产品。这是我的密码: 在我的表格FrmFind中: NorthwindDataContext dc; private void FrmFind_Load(object sender, EventArgs e) { dc = new Northw

使用绑定到绑定到类的BindingSource控件的datagridview,我想知道如何将BindingSource定位到特定记录,也就是说,当我在文本框中键入产品名称时,BindingSource应该移动到该特定产品。这是我的密码:

在我的表格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;
        }
    }
NorthwindDataContext dc;
私有void FrmFind_Load(对象发送方,事件参数e)
{
dc=新的NorthwindDataContext();
var qry=(来自dc.产品中的p
选择p.ToList();
FindAbleBindingList=新的FindAbleBindingList(qry);
productBindingSource.DataSource=list.OrderBy(o=>o.ProductName);
}
私有void textBox1\u TextChanged(对象发送方,事件参数e)
{
TextBox tb=发送方作为TextBox;
int index=productBindingSource.Find(“ProductName”,tb.Text);
如果(索引>=0)
{
productBindingSource.Position=索引;
}
}
在程序类中:

    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
        }
    }
public类FindAbleBindingList:BindingList
{
公共查找绑定列表()
:base()
{
}
公共查找绑定列表(列表)
:基本(列表)
{
}
受保护的重写int FindCore(PropertyDescriptor属性,对象键)
{
for(int i=0;i

如何实现find方法以使其工作?

您可以将
BindingSource.find()
方法与
Position
属性相结合

例如,如果您的文本框中有类似的内容已更改事件处理程序:

private void textBox1_TextChanged(object sender, EventArgs e)
{
    TextBox tb = sender as TextBox;
    int index = bs.Find("Product", tb.Text);

    if (index >= 0)
    {
        bs.Position = index;
    }
}
这当然取决于很多事情,比如绑定源的数据源所具有的Find方法的特定实现

在您不久前提出的一个问题中,我为您提供了一个Find的实现,它可以处理完全匹配。下面是一个稍微不同的实现,它将查看正在检查的属性的开始:

protected override int FindCore(PropertyDescriptor property, object key)
{
    // Simple iteration:
    for (int i = 0; i < Count; i++)
    {
        T item = this[i];
        if (property.GetValue(item).ToString().StartsWith(key.ToString()))
        {
            return i;
        }
    }
    return -1; // Not found
}
为绑定源设置数据源时,包括扩展方法
OrderBy
——选中此项将显示它返回IORDerenumerable,即MSDN上描述的接口。请注意,此接口没有Find方法,因此即使底层的
FindableBindingList
支持Find,绑定源也不知道它

有几种解决方案(我认为最好的方法是扩展FindableBindingList,以支持对列表进行排序和排序),但对于当前代码来说,最快的方法是提前排序,如下所示:

dc = new NorthwindDataContext();

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

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

productBindingSource.DataSource = list;
dc=new NorthwindDataContext();
var qry=(来自dc.产品中的p
选择p).OrderBy(p=>p.ProductName).ToList();
FindAbleBindingList=新的FindAbleBindingList(qry);
productBindingSource.DataSource=列表;


在WinForms中,对于您要做的事情,没有完全现成的解决方案——它们都需要一些定制代码,您需要将这些代码组合在一起,以满足您自己的需求。

我采用了不同的方法。我认为,以编程方式,在找到匹配项之前,必须检查每个记录,所以我只是使用MoveNext方法进行迭代,直到找到匹配项。不确定起始位置是否是第一条记录,所以我使用MoveFirst方法来确保它是第一条记录

有一个假设,那就是你正在搜索的内容在该列中是唯一的。在我的例子中,我希望匹配一个标识整数

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

我对提供的两个答案都不感兴趣。以下是我对我的问题的看法:

// 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;
}
//在BindingSource中创建一个项目列表,并使用labda查找您的行:
var QuickAccessCode=customerListBindingSource.List.OfType()
.ToList().Find(f=>f.QuickAccessCode==txtQAC.Text);
//然后使用indexOf在bindingSource中查找对象:
var pos=customerListBindingSource.IndexOf(QuickAccessCode);
如果(位置<0)
{
MessageBox.Show(“找不到”+txtQAC.Text);
}
其他的
{
mainFrm.customerListBindingSource.Position=pos;
}

设置位置属性。我已经检查了该链接,它没有回答我的问题。也许这会更有帮助。之前也检查了它,该实现数据集不是我的数据源类型。我已经按照之前的建议在项目中实现了BindingList,现在我在查询查找之前将该列表传递给bindingsource控件。当我运行上面的代码时,我再次得到异常:System.NotSupportedException未处理Source=System StackTrace:at System.ComponentModel.BindingList
1.FindCore(PropertyDescriptor prop,Object key)at System.ComponentModel.BindingList
1.System.ComponentModel.IBindingList.Find(PropertyDescriptor属性,对象键),你有什么想法吗?所以你得到了同样的例外-你没有实现find方法。在这一点上,帮助你变得非常困难,你似乎做了很多你没有告诉我们的事情,然后发布了一些与你所遇到的错误不相关的问题。如果你有一个支持find的绑定列表,那么你就可以了查找和索引,并从该索引设置位置。我将检查BindingList的实现。David,可能正如您所说,我在这里没有提到的某些东西会导致出现此错误。第一次我在Filter方法上发布问题,第二次我在find方法上发布问题,我认为这没有什么害处。我不要隐藏我在这条线索中找到你的喜悦,因为多亏了你,我学到了有趣的东西。既然你确信你所说的,那么我请你耐心等待一段时间
// 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;
}