Filtrar um DataGrid em WPF
carrego uma lista de objectos num datagrid com isto:
dataGrid1.Items.Add(model);
OS model
tornam-se dados de uma base de dados. Tem um Id(int)
, Name(string)
e Text(string)
model
. Como posso filtrar o datagrid agora, quando eu digito algo em uma caixa de texto?
Eu estava nesta página. http://msdn.microsoft.com/en-us/library/vstudio/ff407126 (V = vs. 100).aspx mas eu não entendo o código de lá e não posso explicar como devo transpor isso para o meu problema.
5 answers
Existem várias formas de filtrar a recolha
Vamos sugerir que esta é a sua classe de itens.public class Model
{
public string Name
{
get;
set;
}
}
E a tua colecção parece
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" });
Via 1 (Predicado):
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;
}
Caminho 2 (FilterEventHandler):
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;
}
}
Extensão da Informação à Via 1
Se necessitar de condições múltiplas ou de um filtro complexo, pode adicionar um método ao seu Predicat
// your Filter
var yourComplexFilter= new Predicate<object>(ComplexFilter);
private bool ComplexFilter(object obj)
{
//your logic
}
Esta é uma implementação simples de usar a propriedade filtrante da ICollectionView. Suponha que o seu XAML contém isto:
<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>
Depois, no construtor, poderá obter a vista predefinida para os seus dados, onde poderá definir o predicado do filtro que será executado para cada item da sua colecção. A janela de recolha não saberá quando deverá actualizar a colecção, pelo que terá de chamar a actualização quando o Utilizador carregar no botão Procurar.
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();
}
Neste url você pode encontrar mais descrição pormenorizada das colectâneas: http://wpftutorial.net/DataViews.html
@WiiMaxx, não posso comentar como representante insuficiente. eu seria um pouco mais cuidadoso sobre os moldes diretos lá. Eles podem ser lentos para uma coisa e para outra, se o mesmo filtro foi aplicado a uma grade contendo diferentes tipos de dados complexos, você teria uma Invalidcastexcepção.
// your Filter
var yourCostumFilter= new Predicate<object>(item =>
{
item = item as Model;
return item == null || item.Name.Contains("Max");
});
Isto não lhe irá quebrar o datagrid e não irá filtrar os resultados se o elenco falhar. Menos impacto para seus usuários se você ficar com o código errado. Além disso, o filtro será mais rápido devido ao"as" operador não fazendo qualquer tipo de coerção explícita como a operação cast direto vai.
Pode usar o filtro dataview para filtrar as linhas datagrid.
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();
Onde o" datable "é o" datasource "dado ao seu datagrid e usando o construtor de cadeias de caracteres, você constrói a pesquisa do filtro onde "Filter String" é o texto que deseja procurar no seu datagrid e configurá-lo para dataview e, finalmente, definir a dataview como itemsource para o seu datagrid e actualizá-lo.