Je charge une liste d'objets dans une grille de données avec ceci:
dataGrid1.Items.Add(model);
Les model
deviennent des données d'une base de données. Il a une Id(int)
, Name(string)
et Text(string)
Dans ma grille de données, je ne montre que le nom de la model
. Comment puis-je filtrer la grille de données maintenant, lorsque je saisis quelque chose dans une zone de texte?
J'étais sur cette page: http://msdn.Microsoft.com/en-us/library/vstudio/ff407126(v=vs.100).aspx mais je ne comprends pas le code à partir de là et je ne peux pas expliquer comment je devrais transposer cela pour mon problème.
il y a plusieurs façons de filtrer Collection
suggérons ceci est votre classe d'objet
public class Model
{
public string Name
{
get;
set;
}
}
et votre collection ressemble à
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;
}
}
si vous avez besoin de plusieurs conditions ou d’un filtre complexe, vous pouvez ajouter une méthode à votre Predicat
// your Filter
var yourComplexFilter= new Predicate<object>(ComplexFilter);
private bool ComplexFilter(object obj)
{
//your logic
}
Ceci est une implémentation simple de l'utilisation de la propriété Filter de ICollectionView. Supposons que votre XAML contienne ceci:
<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>
Ensuite, dans le constructeur, vous pouvez obtenir la vue par défaut pour vos données, où vous pouvez définir le prédicat de filtre qui sera exécuté pour chaque élément de votre collection. Le CollectionView ne saura pas quand il doit mettre à jour la collection, vous devez donc appeler Actualiser lorsque l'utilisateur clique sur le bouton de recherche.
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();
}
Vous trouverez une description plus détaillée de CollectionViews à cette adresse: http://wpftutorial.net/DataViews.html
@WiiMaxx, je ne peux pas commenter car pas assez de représentants. Je ferais un peu plus attention aux diffusions directes là-bas. Ils peuvent être lents pour une chose et pour une autre, si le même filtre était appliqué à une grille contenant différentes données de type complexe, vous auriez une exception InvalidCastException.
// your Filter
var yourCostumFilter= new Predicate<object>(item =>
{
item = item as Model;
return item == null || item.Name.Contains("Max");
});
Cela ne cassera pas votre grille de données et ne filtrera pas les résultats si la conversion échoue. Moins d'impact pour vos utilisateurs si vous vous trompez de code. De plus, le filtre sera plus rapide du fait que l'opérateur "en tant que" n'effectue aucune contrainte de type explicite, contrairement à l'opération de diffusion directe.
Vous pouvez utiliser le filtre d'affichage du journal afin de filtrer les lignes de la grille de données.
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();
Où "datatable" est la source de données donnée à votre grille de données et à l'aide du générateur de chaînes de caractères, vous construisez la requête de filtre, où "Chaîne de filtre" correspond au texte que vous souhaitez rechercher dans votre grille de données et définissez-le sur affichage de données, puis définissez la vue en tant que source d'éléments sur votre grille de données et le rafraîchir.
examinez DataBinding -> dans votre cas, n’ajoutez pas d’éléments à votre grille, mais définissez le
<Datagrid ItemsSource="{Binding MyCollectionOfModels}" />
ou
dataGrid1.ItemsSource = this._myCollectionOfModels;
et si vous voulez une sorte de filtrage, de tri, de regroupement, regardez CollectionView