1

複数の列で BindingSource の Find メソッドを使用することは可能ですか?

たとえば、現在のペットを表示するグリッドビューがあるとします。cboPetType と cboGender の 2 つのコンボボックス。これら 2 つのコンボボックスの値に基づいて Pet テーブルに新しいレコードを作成するボタン。

ここで、PetType/Gender の各組み合わせ (Dog - M、Cat - F など) のうち 1 つだけが必要だとします。そのため、BindingSource に Dog - M ペットがあり、ユーザーがコンボボックスから Dog と M を選択した場合、組み合わせが既に存在することをユーザーに通知するのを止めたいと思います。

過去に、BindingSource.Find メソッドを使用して同様のことを行いましたが、私が知る限り、それは 1 つの列を検索する場合にのみ有効です (つまり、BindingSource.Find("PetType", cboPetType.SelectedValue);)。 .

複数の列に基づいて bindingsource を検索することは可能ですか? そうでない場合、希望する結果を達成するための提案はありますか? どんなアドバイスでも大歓迎です!

4

5 に答える 5

2

誰かが同じ問題に遭遇した場合に備えて、別のより簡単な解決策。これは、BindingSource が DataView の場合に機能します。

MyBindingSource.Sort = "Column1,Column2"
Dim underlyingView As DataView = DirectCast(MyBindingSource.List, DataView)
Dim searchVals As New List(Of Object)
searchVals.Add("SearchString1")
searchVals.Add("SearchString2")

Dim ListIndex as Integer = underlyingView.Find(searchVals.ToArray)

If ListIndex >=0 Then
    MyBindingList.Position = ListIndex
Else
    'No matches, so what you need to do...
End If
于 2010-02-24T19:41:28.253 に答える
2

いいえ、残念ながらこれは不可能です。特定のデータ ソースが与えられた場合、そのような検索はかなり単純になる可能性がありますが、より一般的な方法 (のようにBindingSource) で検索を行うと、透過性が少し低下します。1 つは、構文がわかりにくいことです。これはやや不自然な解決策です:

public class Key
{
    public string PropertyName {get; set;}
    public object Value {get; set;}
}

public static int Find(this BindingSource source, params Key[] keys)
{
    PropertyDescriptor[] properties = new PropertyDescriptor[keys.Length];

    ITypedList typedList = source as ITypedList;

    if(source.Count <= 0) return -1;

    PropertyDescriptorCollection props;

    if(typedList != null) // obtain the PropertyDescriptors from the list
    {
        props = typedList.GetItemProperties(null);
    }
    else // use the TypeDescriptor on the first element of the list
    {
        props = TypeDescriptor.GetProperties(source[0]);
    }

    for(int i = 0; i < keys.Length; i++)
    {
        properties[i] = props.Find(keys[i].PropertyName, true, true); // will throw if the property isn't found
    }

    for(int i = 0; i < source.Count; i++)
    { 
        object row = source[i];
        bool match = true;

        for(int p = 0; p < keys.Count; p++)
        {
            if(properties[p].GetValue(row) != keys[p].Value))
            {
                match = false;
                break;
            }
        }

        if(match) return i;
    }

    return -1;
}

次のように呼び出すことができます。

BindingSource source = // your BindingSource, obviously 

int index = source.Find(
    new Key { PropertyName = "PetType", Value = "Dog" },
    new Key { PropertyName = "Gender", Value = "M" });

これを使用できるようにするには、よりスマートな比較アルゴリズムが必要ですが、それは読者の課題として残します。の実装を確認IComparableすることは良い出発点です。それにもかかわらず、その概念は、実装の特定のポイントに関係なく継続する必要があります。

これは、基になるデータ ソースによって実装される可能性のあるパフォーマンスの最適化を利用しないことに注意してくださいFind

于 2009-11-19T22:40:25.220 に答える
1

これは、上記の例に基づいた私のバージョンです。それは非常にうまく機能します。

Public Class clsBSHelpers

    Public Structure Key

        Public PropertyName As String
        Public Value As Object

        Sub New(ByVal pPropertyName As String, ByVal pValue As Object)
            PropertyName = pPropertyName
            Value = pValue
        End Sub

    End Structure

    Public Shared Function Find(ByVal Source As BindingSource, ByVal ParamArray keys As Key()) As Boolean

        Dim sb As New Text.StringBuilder
        For i As Integer = 0 To keys.Length - 1
            If sb.Length > 0 Then
                sb.Append(",")
            End If
            sb.Append(keys(i).PropertyName)
        Next

        Source.Sort = sb.ToString
        Dim underlyingView As DataView = DirectCast(Source.List, DataView)
        Dim searchVals As New List(Of Object)
        For i As Integer = 0 To keys.Length - 1
            searchVals.Add(keys(i).Value)
        Next

        Dim ListIndex As Integer = underlyingView.Find(searchVals.ToArray)

        If ListIndex >= 0 Then
            Source.Position = ListIndex
            Find = True
        Else
            Find = False
            'No matches, so what you need to do...
        End If

        Return Find

    End Function

End Class

私はそれを次のように呼びます:

e.Cancel = clsBSHelpers.Find(CastingBedBindingSource, _
                             New clsBSHelpers.Key("PlantID", m_PlantID), _
                             New clsBSHelpers.Key("LineBedNUmber", m_LineBedNumber))

シンプルが好きな方の参考になれば幸いです。

于 2012-11-06T17:03:45.040 に答える
0
var sorcobj = SorcBs.Current as Data.Student;

if (sorcobj == null) return;

TrgtBs.Position = TrgtBs.List.IndexOf(TrgtBs.List.OfType<Data.Student>().FirstOrDefault(s => s.NAME == sorc.NAME));
于 2018-05-10T08:34:09.647 に答える