BindingSource.Find多列 [英] BindingSource.Find Multiple Columns

查看:207
本文介绍了BindingSource.Find多列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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.

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

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.

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

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!

推荐答案

否,不幸的是,这是不可能的.尽管在给定特殊数据源的情况下,这样的搜索可能会相当简单,但是以更通用的方式(如BindingSource)进行此操作的透明度会降低一些.首先,语法将不那么明显.这是一个人为设计的解决方案:

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

您可以这样称呼它:

BindingSource source = // your BindingSource, obviously 

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

请记住,要使此功能可用,您确实需要一个更智能的比较算法,但我将其留给读者练习.检查IComparable的实现是一个好的开始.尽管如此,该概念仍应坚持下去,而不管具体的实现点如何.

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.

请注意,这不会利用基础数据源可能实现的任何可能的性能优化,而单列Find会利用.

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.

这篇关于BindingSource.Find多列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆