开发者

Using Linq to filter a ComboBox.DataSource?

in another topic, I've stumbled over this very elegant solution by Darin Dimitrov to filter the DataSource of one ComboBox with the selection of another ComboBox: how to filter combobox in combobox using c#

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

I would like to do a similar thing, but intead of filtering by a second combobox, I would like to filter by the text of a TextBox. (Basically, instead of choosing from a second ComboBox, the user simply enters his filter in to a TextBox). However, it turned out to be not as straight forward as I had hoped it would be. I tried stuff as the following, but failed miserably:

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

ds is the DataSet which I would like to use as filtered DataSource. "Adresse" is one DataTable in this DataSet. It contains a DataColumn "AdrLabel". Now I would like to display only those "AdrLabel", which contain the string from the user input. (Currently, %TEST% replaces the textbox.text.)

The above code fails because the lambda expression does not return Bool. But I am sure, there are also other problems (which type should I use for IEnumerable? Now it's DataSet, but Darin used String. But how could I convert a DataSet to a string?

Yes, I am as much newbyish as it gets, my experience is "void", and publicly so. So please forgive me my rather stupid questions.

Your help is greatly appreciated, because I can't solve this开发者_开发知识库 on my own (tried hard already).

Thank you very much!

Pesche

P.S. I am only using Linq to achieve an uncomplicated filter for the ComboBox (avoiding a View). The rest is not based on Linq, but on oldstyle Ado.NET (ds is filled by an SqlDataAdapter), if that's of any importance.


LINQ does not seem, to me, like an obvious solution here. Your data is already loaded into a DataSet structure, so you should be able to do something like this:

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

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

To address the actual problems in your current code:

  1. If ds is of type DataSet, casting it to IEnumerable<DataSet> will fail.
  2. DataTable.Select returns an array of rows, not a boolean.
  3. Ignoring #1 and #2, your Where() call would return zero, one or more DataSet instances which each have a table named "Adresse" with at least one row matching the filter. Hence, you end up binding your presentational control to a set of DataSet instances, which is not what you need.


If you want to use LINQ, then you'll need to add a reference System.Data.DataSetExtensions. You can then query your DataSet in a "linqish" manner.

The blog post Querying DataSets – Introduction to LINQ to DataSet by Erick Thompson, a PM at Microsoft is a good introduction to LINQ to DataSets

Here's a very crude example:

XAML

<StackPanel>

    <TextBox x:Name="MyFilter" />

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

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

</StackPanel>

Code Behind

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜