使用绑定到绑定到LINQ to SQL类的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;
}
}
在程序类中:
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
}
}
如何实现find方法以使其工作?
答案 0 :(得分:12)
您可以将BindingSource.Find()
方法与Position
属性结合使用。
例如,如果在TextBox更改的事件处理程序中有类似的内容:
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
}
请注意,上述方法区分大小写 - 如果需要,可以将StartsWith更改为不区分大小写。
关于.Net的工作方式,需要注意的一件事是,对象的实际类型始终不够 - 声明的类型是消费代码所知道的。
这就是为什么在调用Find方法时遇到NotSupported
异常的原因,即使您的BindingList
实现具有Find方法 - 接收此绑定列表的代码也不知道查找。
原因在于以下几行代码:
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);
为绑定源设置数据源时,包括扩展方法OrderBy
- 选中此选项表示它返回IOrderedEnumerable,并在MSDN上描述here接口。请注意,此接口没有Find方法,因此即使基础FindableBindingList<T>
支持查找绑定源也不知道它。
有几种解决方案(我认为最好的是扩展你的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;
在WinForms中,没有完全开箱即用的解决方案可用于您正在尝试的事情 - 它们都需要一些自定义代码,您需要将它们组合在一起以满足您自己的要求。
答案 1 :(得分:1)
我采取了不同的方法。我想,以编程方式,必须检查每个记录,直到找到匹配,所以我只是使用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;
}
}
}
答案 2 :(得分:1)
我真的不在乎提供的任何答案。这是我想出的解决方案:
// 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;
}