BindingSource.查找多个列

发布于 2024-08-12 01:58:51 字数 436 浏览 12 评论 0原文

是否可以在多个列上使用 BindingSource 的 Find 方法?

例如,假设我有一个显示当前宠物的网格视图;两个组合框,cboPetType 和 cboGender;以及一个按钮,用于根据这两个组合框的值在 Pet 表中创建新记录。

现在,假设我只想要每种宠物类型/性别组合中的一种(狗 - M、猫 - F 等)。因此,如果我的 BindingSource 中有一个 Dog - M 宠物,并且用户从组合框中选择 Dog 和 M,我想阻止用户通知他们组合已经存在。

过去,我曾使用 BindingSource.Find 方法执行类似的操作,但据我所知,这仅适用于搜索一列(即 BindingSource.Find("PetType", cboPetType.SelectedValue);) 。

是否可以根据多列搜索绑定源?如果没有,有什么建议可以达到我想要的结果吗?非常感谢任何建议!

Is it possible to use the Find method of a BindingSource on multiple columns?

For example, say I have a gridview displaying current pets; two comboboxes, cboPetType and cboGender; and a button to create a new record into the Pet table based on the values of these two comboboxes.

Now, let's say I only want one of each PetType/Gender combination (Dog - M, Cat - F, etc.). So, if I have a Dog - M pet in my BindingSource and a user selects Dog and M from the comboboxes, I would like to stop the user to inform them that combination already exists.

In the past, I have used the BindingSource.Find method to do something similar, but, as far as I can tell, that is only good for searching one column (i.e. BindingSource.Find("PetType", cboPetType.SelectedValue);).

Is it possible to search a bindingsource based on multiple columns? If not, any suggestions to achieve my desired result? Any advice is greatly appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

剪不断理还乱 2024-08-19 01:58:51

不,不幸的是这是不可能的。虽然在给定特定数据源的情况下,此类搜索可能相当简单,但以更通用的方式(如 BindingSource 那样)进行搜索则不太透明。其一,语法不太明显。这是一个有点人为的解决方案:

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 则可以。

No, unfortunately this isn't possible. While it's likely that given a particular data source that such a search would be fairly simple, doing it in a more generic way (as the BindingSource would) is a little less transparent. For one, the syntax would be less than obvious. Here's a somewhat contrived solution:

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;
}

You can call it like this:

BindingSource source = // your BindingSource, obviously 

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

Bear in mind that for this to be usable, you really need a smarter comparison algorithm, but I'll leave that as an exercise to the reader. Checking for an implementation of IComparable would be a good start. Nonetheless, the concept should carry through regardless of that particular point of implementation.

Note that this won't take advantage of any of the possible performance optimizations that might be implemented by the underlying data source, whereas the single column Find would.

我的奇迹 2024-08-19 01:58:51

另一个更简单的解决方案,以防有人遇到同样的问题。当 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

Another simpler solution, in case someone runs into the same issue. This works when the BindingSource is a 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
雪化雨蝶 2024-08-19 01:58:51

这是我基于上述示例的版本。它运作得很好。

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))

希望这可以帮助那些喜欢简单的人。

This is my version based on the above examples. It works very well.

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

I call it thus:

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

Hope this helps those that like it simple.

树深时见影 2024-08-19 01:58:51

更简单的解决方案是使用扩展方法:

var id1 = "id1";
var id2 = "id2";

var data = bindingSource1.Cast<DataModelType>().Single(r => r.ID1 == id1 && r.ID2 == id2);
bindingSource1.Position = bindingSource1.IndexOf(data);

The more simple solution is by using Extension Method:

var id1 = "id1";
var id2 = "id2";

var data = bindingSource1.Cast<DataModelType>().Single(r => r.ID1 == id1 && r.ID2 == id2);
bindingSource1.Position = bindingSource1.IndexOf(data);
刘备忘录 2024-08-19 01:58:51
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));
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));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文