简体   繁体   English

使用Contains方法访问DataBound ComboBox的ComboBox.Items

[英]Accessing ComboBox.Items with Contains method for DataBound ComboBox

Summary: 摘要:

I want to check the current ComboBox.text value against the list of items in a ComboBox that is assigned a DataSource at run time. 我想对照在运行时分配了数据源的ComboBox中的项目列表检查当前ComboBox.text值。 If the text doesn't match an item in the list then it will select the first item in the list. 如果文本与列表中的项目不匹配,则它将选择列表中的第一项。


Here is what I originally tried: 这是我最初尝试的方法:

' This Load function is just here to give an example of how I bound the ComboBox '
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    Me.myComboBox.DisplayMember = "something"
    Me.myComboBox.ValueMember = "otherthing"
    Me.myComboBox.DataSource = Me.myDataTable
End Sub

' This function is copy/pasted directly out of my code '
Private Sub myComboBox_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles myComboBox.Validating
    If Not DirectCast(sender, ComboBox).Items.Contains(DirectCast(sender, ComboBox).Text) Then
        DirectCast(sender, ComboBox).SelectedValue = -1
    End If
End Sub

However the above code does not work as expected because when inspecting the myComboBox.Items property at run time, it is actually a collection of System.Data.DataRowView objects. 但是上述代码无法按预期方式工作,因为在运行时检查myComboBox.Items属性时,它实际上是System.Data.DataRowView对象的集合。 So basically it is comparing a String to DataRowView.ToString() which is always false unless the myComboBox.Text value is in fact "System.Data.DataRowView"... 因此,基本上它将StringDataRowView.ToString()进行比较,除非myComboBox.Text值实际上是“ System.Data.DataRowView”,否则它始终为false。


So I thought 所以我认为

"Hey, lets make an extension method to search all the items of the DataViewRow and see if my requested value is in there!", but it's not going as planned... “嘿,让我们做一个扩展方法来搜索DataViewRow所有项目,看看我请求的值是否在里面!”但是它并没有按计划进行...

 <Extension()> 
Private Function Contains_databound(ByVal items As ComboBox.ObjectCollection, ByVal value As Object) As Boolean
    Dim Success As Boolean = False

    For Each itm In items
        Dim item As DataRowView = Nothing

        Try
            item = DirectCast(itm, DataRowView)
        Catch ex As Exception
            Throw New Exception("Attempted to use a Contains_databound method on a non databound object", New Exception(ex.Message))
        End Try

        If Not IsNothing(item) Then
            For Each rowItem In item.Row.ItemArray
                Dim v1 As String = TryCast(rowItem, String)
                Dim v2 As String = TryCast(value, String)

                If Not IsNothing(v1) And Not IsNothing(v2) Then
                    If v1.Equals(v2) Then
                        Success = True
                    End If
                End If
            Next
        End If
    Next
    Return Success
End Function

I know that looks weird, but the code prettify won't work right if the <Extension()> part isn't separated. 我知道这看起来很奇怪,但是如果未分隔<Extension()>部分,则整理代码将无法正常工作。 When I attempt to use my extension method in my main code, I get an error about my extension method not being a member of ComboBox.ObjectCollection which seems bogus to me because in the extension method I am specifically saying that the first parameter is a ComboBox.ObjectCollection . 当我尝试在我的主代码中使用扩展方法时,我得到一个关于我的扩展方法不是ComboBox.ObjectCollection成员的错误,这对我来说似乎是虚假的,因为在扩展方法中,我具体是说第一个参数是ComboBox.ObjectCollection

Private Sub myComboBox_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles myComboBox.Validating
    If DirectCast(sender, ComboBox).Items.Contains_databound(DirectCast(sender, ComboBox).Text) Then
        DirectCast(sender, ComboBox).SelectedValue = -1
    End If
End Sub

Infamous "HOW TO BRAIN SURGERY WITH POTATO" request... 臭名昭著的“如何用土豆进行脑外科手术”要求...

How can I determine that the text a user inputs into a databound ComboBox is in the list of items from the DataSource? 如何确定用户输入到数据绑定的ComboBox中的文本在DataSource的项目列表中?

Side note: C# answers are fine so long as they have a VB.NET counterpart 旁注:C#答案很好,只要它们具有VB.NET副本即可

What you're actually trying to determine is whether the displayed text of any item matches some other value. 您实际上要确定的是任何项目的显示文本是否与其他值匹配。 To get the displayed text of an item you call GetItemText . 要获取项目的显示文本,请调用GetItemText I'll post an example. 我将举一个例子。

Here's an extension method that will do the job: 这是可以完成这项工作的扩展方法:

Imports System.Runtime.CompilerServices

Public Module ComboBoxExtensions

    <Extension>
    Public Function ContainsItemText(source As ComboBox, itemText As String) As Boolean
        Return source.Items.Cast(Of Object).Any(Function(item) source.GetItemText(item) = itemText)
    End Function

End Module

I think the following code represents what you described. 我认为以下代码代表了您所描述的内容。 Basically look at the btn.Clicked event code. 基本上看btn.Clicked事件代码。

public class FormAB : Form {

    ComboBox combo = new ComboBox { DropDownStyle = ComboBoxStyle.DropDown, Dock = DockStyle.Top };
    Button btn = new Button { Text = "Button", Dock = DockStyle.Top };

    public FormAB() {
        Controls.Add(btn);
        Controls.Add(combo);

        DataTable table = new DataTable();
        table.Columns.Add("FirstName");
        table.Columns.Add("BirthDate", typeof(DateTime));

        table.Rows.Add("Alan", DateTime.Today.AddYears(-20));
        table.Rows.Add("Bob", DateTime.Today.AddYears(-35));

        combo.DataSource = table;
        combo.DisplayMember = "FirstName";
        combo.ValueMember = "FirstName";

        btn.Click += delegate {
            Object rv = combo.Items.Cast<Object>().Where(r => combo.GetItemText(r) == "Bob").FirstOrDefault();
            // either/or
            //Object rv = combo.Items.Cast<DataRowView>().Where(r => (String) r[combo.DisplayMember] == "Bob").FirstOrDefault();
            if (rv == null && combo.Items.Count > 0)
                rv = combo.Items[0];
            combo.SelectedItem = rv;
        };
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM