是否可以在多列上使用BindingSource的Find方法?
例如,假设我有一个显示当前宠物的网格视图;两个组合框,cboPetType和cboGender;以及一个按钮,根据这两个组合框的值在Pet表中创建一条新记录。
现在,假设我只想要每个PetType / Gender组合中的一个(Dog-M,Cat-F等)。所以,如果我在BindingSource中有一个Dog-M宠物,并且用户从组合框中选择了Dog和M,我想阻止用户通知他们组合已经存在。
过去,我使用BindingSource.Find方法做类似的事情,但据我所知,这只适用于搜索一列(即BindingSource.Find(“PetType”,cboPetType.SelectedValue) );)
是否可以根据多个列搜索bindingsource?如果没有,任何建议,以达到我想要的结果?非常感谢任何建议!
答案 0 :(得分:3)
不,不幸的是,这是不可能的。虽然给定一个特定的数据源可能会使这样的搜索变得相当简单,但是以更通用的方式(如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
会实现。
答案 1 :(得分: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
答案 2 :(得分:0)
这是基于以上示例的我的版本。它运作得很好。
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))
希望这有助于那些喜欢它的人。
答案 3 :(得分:0)
更简单的解决方案是使用扩展方法:
$('.child').mousedown(function(){
//what can I write here to prevent parent's click event from fireing?
//I've tried event.stopPropagation() as well as
//event.stopImmediatePropagation() already
});
$('.parent').on('click',function(){...})
答案 4 :(得分: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));