使用Linq过滤ComboBox.DataSource?

时间:2010-03-21 17:56:02

标签: c# linq combobox dataset filter

在另一个主题中,我偶然发现Darin Dimitrov使用另一个ComboBox选择过滤一个ComboBox的DataSource这个非常优雅的解决方案: how to filter combobox in combobox using c#

combo2.DataSource = ((IEnumerable<string>)c.DataSource)
.Where(x => x == (string)combo1.SelectedValue);

我想做类似的事情,但是通过第二个组合框进行过滤,我想通过TextBox的文本进行过滤。 (基本上,用户只需将其过滤器输入到TextBox中,而不是从第二个ComboBox中选择)。然而,事实证明并不像我希望的那样直截了当。我尝试了以下内容,但是失败了:

     cbWohndresse.DataSource = ((IEnumerable<DataSet>)ds)
            .Where(x => x.Tables["Adresse"].Select("AdrLabel LIKE '%TEST%'"));
        cbWohndresse.DisplayMember = "Adresse.AdrLabel";
        cbWohndresse.ValueMember = "Adresse.adress_id";

ds DataSet ,我想将其用作过滤后的DataSource。 “Adresse”是此DataSet中的一个 DataTable 。它包含 DataColumn“AdrLabel”。现在我想只显示那些包含用户输入字符串的“AdrLabel”。 (目前,%TEST%取代了textbox.text。)

上面的代码失败,因为lambda表达式不返回Bool。但我确信,还有其他问题(我应该为IEnumerable使用哪种类型?现在它是DataSet,但是Darin使用了String。但是我怎样才能将DataSet转换为字符串?

是的,我和它一样多新鲜,我的经历是“无效的”,而且是公开的。所以请原谅我相当愚蠢的问题。

非常感谢您的帮助,因为我无法自己解决这个问题(已经努力了)。

非常感谢!

Pesche

P.S。我只使用Linq为ComboBox实现一个简单的过滤器(避免使用View)。其余的不是基于Linq,而是基于旧式Ado.NET(ds由SqlDataAdapter填充),如果这是重要的。

2 个答案:

答案 0 :(得分:4)

对我来说,LINQ似乎不是一个明显的解决方案。您的数据已加载到DataSet结构中,因此您应该可以执行以下操作:

var adresse = ds.Tables["Adresse"];
adresse.DefaultView.RowFilter = "AdrLabel LIKE '%TEST%'";

cbWohndresse.DataSource = adresse;
cbWohndresse.DisplayMember = "AdrLabel";
cbWohndresse.ValueMember = "adress_id"
cbWohndresse.DataBind();

解决当前代码中的实际问题:

  1. 如果ds的类型为DataSet,则将其投放到IEnumerable<DataSet>将会失败。
  2. DataTable.Select返回一个行数组,而不是布尔值。
  3. 忽略#1和#2,您的Where()调用将返回零,一个或多个DataSet实例,每个实例都有一个名为“Adresse”的表,其中至少有一行与过滤器匹配。因此,您最终将您的演示控制绑定到一组DataSet个实例,而不是您需要的实例。

答案 1 :(得分:1)

如果您想使用LINQ,则需要添加引用System.Data.DataSetExtensions。然后,您可以以“linqish”方式查询DataSet。

微软总裁Erick Thompson撰写的博客文章Querying DataSets – Introduction to LINQ to DataSet是对LINQ to DataSet的一个很好的介绍

这是一个非常粗略的例子:

<强> XAML

<StackPanel>

    <TextBox x:Name="MyFilter" />

    <ComboBox x:Name="MyComboBox" 
              ItemsSource="{Binding}"
              DisplayMemberPath="AdrLabel" />

    <Button Click="OnFilterClick">Filter</Button>

</StackPanel>

代码背后

public partial class FilteredDataSet : Window
{
    public FilteredDataSet()
    {
        InitializeComponent();

        CreateDataContext();
        MyComboBox.DataContext = MyDataSet.Tables[0];
    }

    private DataSet MyDataSet { get; set; }
    private void CreateDataContext()
    {
        var ds = new DataSet();
        var dt = new DataTable( "Adresse" );
        ds.Tables.Add( dt );

        var dc = new DataColumn( "AdrLabel" );
        dt.Columns.Add( dc );

        DataRow dr = dt.NewRow();
        dr[0] = "one";
        dt.Rows.Add( dr );

        dr = dt.NewRow();
        dr[0] = "honed";
        dt.Rows.Add( dr );

        dr = dt.NewRow();
        dr[0] = "obiwone";
        dt.Rows.Add( dr );

        dr = dt.NewRow();
        dr[0] = "won";
        dt.Rows.Add( dr );

        MyDataSet = ds;

    }
    private void OnFilterClick( object sender, RoutedEventArgs e )
    {
        string filter = MyFilter.Text;

        var context = MyDataSet.Tables[0].AsEnumerable()
            .Where( dr => dr.Field<string>( "AdrLabel" ).Contains( filter ) )
            .Select( dr => dr.Field<string>( "AdrLabel" ) );

        MyComboBox.DisplayMemberPath = string.Empty;

        MyComboBox.DataContext = context;
    }
}