Reputation: 1332
I load a lists of objects in a datagrid with this:
dataGrid1.Items.Add(model);
The model
become data from a database. It has a Id(int)
, Name(string)
and Text(string)
In my datagrid I show only the Name of the model
. How can I filter the datagrid now, when I enter something in a textbox?
I was at this page: http://msdn.microsoft.com/en-us/library/vstudio/ff407126(v=vs.100).aspx but I don't understand the code from there and I can not explain how I should transpose that for my problem.
Upvotes: 24
Views: 100228
Reputation: 2016
You can use dataview filter in order to filter the datagrid rows.
DataView dv = datatable.DefaultView;
StringBuilder sb = new StringBuilder();
foreach (DataColumn column in dv.Table.Columns)
{
sb.AppendFormat("[{0}] Like '%{1}%' OR ", column.ColumnName, "FilterString");
}
sb.Remove(sb.Length - 3, 3);
dv.RowFilter = sb.ToString();
dgvReports.ItemsSource = dv;
dgvReports.Items.Refresh();
Where the "datatable" is datasource given to your datagrid and using string builder you build the filter query where "Filter String" is the text you want to search in your datagrid and set it to dataview and finally set the dataview as itemsource to your datagrid and refresh it.
Upvotes: 0
Reputation: 77
Leaving this here incase like me you couldn't get the other methods above to work properly.
//Example of my Transaction class
//Transaction(ID, Amount, Description)
ListCollectionView collectionView = new ListCollectionView(List<Transaction>);
collectionView.Filter = (e) =>
{
Transaction transaction = e as Transaction;
if (transaction.Amount >= 0) //When this is true it returns all positive transactions
{
return true;
}
else
{
return false;
}
};
dataGrid.ItemsSource = collectionView;
Upvotes: 0
Reputation: 51
I found a dumb method and know this is an old question but ... Just use the Filter function on items property on the DataGrid object. Like this: (I'm sorry but i learned only VB)
Public Property SearchName As String
Get
Return _SearchName
End Get
Set
_SearchName = Value
DG_drw_overview.Items.Filter = New Predicate(Of Object)(Function(x) x.Name.Contains(Value))
End Set
End Property
This property is changed every time you type something in the textbox. DG_drw_overview is the DataGrid instance. In Predicate the object represents the object you put in the DataGrid.
Then bind the SearchName to textbox
<TextBox x:Name="TB_search"
Text="{Binding SearchName, UpdateSourceTrigger=PropertyChanged}"/>
Set datacontext of the textbox to the main class (usually after InitializeComponent())
TB_search.DataContext = Me
Upvotes: 1
Reputation: 22445
take at look at DataBinding --> in your case dont add items to your grid, but set the itemssource
<Datagrid ItemsSource="{Binding MyCollectionOfModels}" />
or
dataGrid1.ItemsSource = this._myCollectionOfModels;
and if you want some kind of filtering,sorting, grouping look at CollectionView
Upvotes: 0
Reputation: 150
@WiiMaxx, can't comment as not enough rep. I would be a bit more careful about the direct casts there. They can be slow for one thing and for another, if the same filter was applied to a grid holding different complex type data you would have an InvalidCastException.
// your Filter
var yourCostumFilter= new Predicate<object>(item =>
{
item = item as Model;
return item == null || item.Name.Contains("Max");
});
This will not break you datagrid and will not filter the results if the cast fails. Less impact to your users if you get the code wrong. On top of that the filter will be faster due to the "as" operator not doing any explicit type coercion as the direct cast operation will.
Upvotes: 5
Reputation: 5420
there are multiple way's to filter Collection
let's suggesting this is your Item Class
public class Model
{
public string Name
{
get;
set;
}
}
and your collection looks like
var ObColl = new ObservableCollection<Model>();
ObColl.Add(new Model() { Name = "John" });
ObColl.Add(new Model() { Name = "Karl" });
ObColl.Add(new Model() { Name = "Max" });
ObColl.Add(new Model() { Name = "Mary" });
public MainWindow()
{
InitializeComponent();
// Collection which will take your ObservableCollection
var _itemSourceList = new CollectionViewSource() { Source = ObColl };
// ICollectionView the View/UI part
ICollectionView Itemlist = _itemSourceList.View;
// your Filter
var yourCostumFilter= new Predicate<object>(item => ((Model)item).Name.Contains("Max"));
//now we add our Filter
Itemlist.Filter = yourCostumFilter;
dataGrid1.ItemsSource = Itemlist;
}
public MainWindow()
{
InitializeComponent();
// Collection which will take your Filter
var _itemSourceList = new CollectionViewSource() { Source = ObColl };
//now we add our Filter
_itemSourceList.Filter += new FilterEventHandler(yourFilter);
// ICollectionView the View/UI part
ICollectionView Itemlist = _itemSourceList.View;
dataGrid1.ItemsSource = Itemlist;
}
private void yourFilter(object sender, FilterEventArgs e)
{
var obj = e.Item as Model;
if (obj != null)
{
if (obj.Name.Contains("Max"))
e.Accepted = true;
else
e.Accepted = false;
}
}
if need multiple conditions or some complex Filter you can add a method to your Predicat
// your Filter
var yourComplexFilter= new Predicate<object>(ComplexFilter);
private bool ComplexFilter(object obj)
{
//your logic
}
Upvotes: 56
Reputation: 856
This is a simple implementation of using the Filter property of ICollectionView. Suppose your XAML contains this:
<TextBox x:Name="SearchTextBox" />
<Button x:Name="SearchButton"
Content="Search"
Click="SearchButton_OnClick"
Grid.Row="1" />
<DataGrid x:Name="MyDataGrid"
Grid.Row="2">
<DataGrid.Columns>
<DataGridTextColumn Header="Lorem ipsum column"
Binding="{Binding}" />
</DataGrid.Columns>
</DataGrid>
Then in the constructor you can get the default view for your data where you can set the filter predicate which will be executed for every item of your collection. The CollectionView won't know when it should update the collection, so you have to call Refresh when the user clicks the search button.
private ICollectionView defaultView;
public MainWindow()
{
InitializeComponent();
string[] items = new string[]
{
"Asdf",
"qwer",
"sdfg",
"wert",
};
this.defaultView = CollectionViewSource.GetDefaultView(items);
this.defaultView.Filter =
w => ((string)w).Contains(SearchTextBox.Text);
MyDataGrid.ItemsSource = this.defaultView;
}
private void SearchButton_OnClick(object sender, RoutedEventArgs e)
{
this.defaultView.Refresh();
}
At this url you can find a more detailed description of CollectionViews: http://wpftutorial.net/DataViews.html
Upvotes: 9