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:
- If
ds
is of typeDataSet
, casting it toIEnumerable<DataSet>
will fail. DataTable.Select
returns an array of rows, not a boolean.- Ignoring #1 and #2, your
Where()
call would return zero, one or moreDataSet
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 ofDataSet
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;
}
}
精彩评论