6

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メソッドを実装して機能させるにはどうすればよいですか?

4

3 に答える 3

16

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の動作について注意すべき重要な点の1つは、オブジェクトの実際の型が常に十分ではないということです。宣言された型は、消費コードが知っているものです。

NotSupportedこれが、実装にFindメソッドがある場合でも、Findメソッドを呼び出すときに例外が発生する理由です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);

バインディングソースのデータソースを設定するときは、拡張メソッドを含めます。これをチェックすると、MSDNでOrderBy説明されているインターフェイスであるIOrderedEnumerableが返されることがわかります。このインターフェースにはFindメソッドがないため、基になるサポートである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には、実行しようとしていることに対する完全にすぐに使用できるソリューションはありません。すべてのソリューションには、独自の要件に一致するようにまとめる必要のあるカスタムコードが少し必要です。

于 2012-07-30T20:36:24.487 に答える
2

私は別のアプローチを取りました。プログラムで、一致するものが見つかるまですべてのレコードをチェックする必要があると考えたので、一致するものが見つかるまでMoveNextメソッドを使用して繰り返しました。開始位置が最初のレコードになるかどうかわからないので、MoveFirstメソッドを使用してそれが最初のレコードであることを確認しました。

1つの仮定があります。それは、検索しているものがその列で一意であるということです。私の場合、Identity整数と一致することを探していました。

int seekID;        
this.EntityTableBindingSource.MoveFirst();
if (seekID > 0)
{
     foreach (EntityTable sd in EntityTableBindingSource)
     {
         if (sd.ID != seekID)
         {
             this.t_EntityTableBindingSource.MoveNext();
         }
         else
         {
             break;
         }
      }
 } 
于 2016-10-06T20:05:09.447 に答える
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;
}
于 2020-10-14T04:38:36.433 に答える