J'ai un ListView qui peut être filtrée à l'aide d'une zone de texte:Obtenez le nombre d'éléments affichés dans le ListView WPF MVVM
<TextBox TextChanged="txtFilter_TextChanged" Name="FilterLv"/>
De l'avis code-behind je procédez comme suit:
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(this.lv.ItemsSource);
view.Filter = UserFilter;
private bool UserFilter(object item)
{
if (String.IsNullOrEmpty(FilterLv.Text))
return true;
else
{
DataModel m = (item as DataModel);
bool result = (m.Name.IndexOf(Filter.Text, StringComparison.OrdinalIgnoreCase) >= 0 ||
//m.Surname.IndexOf(Filter.Text, StringComparison.OrdinalIgnoreCase) >= 0);
return result;
}
}
private void Filter_TextChanged(object sender, TextChangedEventArgs e)
{
CollectionViewSource.GetDefaultView(this.lv.ItemsSource).Refresh();
}
Maintenant, j'ai placé une étiquette dans la vue et je voudrais que cette étiquette montre le nombre d'éléments actuellement affichés dans la liste.
Comment puis-je le faire? J'ai trouvé des choses comme this mais je ne comprends pas du tout ce qu'est RowViewModelsCollectionView. Dans ce lien, il est suggéré de se lier comme ci-dessous:
<Label Content="{Binding ModelView.RowViewModelsCollectionView.Count}"/>
Quelqu'un pourrait-il me expliquer ou fournir un exemple très peu et simple sur la façon de le faire?
FINAL MISE A JOUR:
Voir modèle:
public class TestViewModel
{
// lv is populated later in code
public ObservableCollection<DataModel> lv = new ObservableCollection<DataModel>();
public ObservableCollection<DataModel> LV
{
get
{
return this.lv;
}
private set
{
this.lv= value;
OnPropertyChanged("LV");
}
}
private CollectionView view;
public TestViewModel()
{
this.view = (CollectionView)CollectionViewSource.GetDefaultView(this.LV);
view.Filter = UserFilter;
}
private string textFilter;
public string TextFilter
{
get
{
return this.textFilter;
}
set
{
this.textFilter= value;
OnPropertyChanged("TextFilter");
if (String.IsNullOrEmpty(value))
this.view.Filter = null;
else
this.view.Filter = UserFilter;
}
}
private bool UserFilter(object item)
{
if (String.IsNullOrEmpty(this.TextFilter))
return true;
else
{
DataModel m = (item as DataModel);
bool result = (m.Name.IndexOf(this.TextFilter, StringComparison.OrdinalIgnoreCase) >= 0 ||
//m.Surname.IndexOf(this.TextFilter, StringComparison.OrdinalIgnoreCase) >= 0);
return result;
}
}
/// <summary>
/// Número de registros en la listview.
/// </summary>
public int NumberOfRecords
{
get
{
return this.view.Count;
}
}
}
Voir (XAML):
<!-- search textbox - filter -->
<TextBox TextChanged="txtFilter_TextChanged"
Text="{Binding TextFilter, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<!-- label to show the number of records -->
<Label Content="{Binding NumberOfRecords}"/>
vue code-behind (xaml.cs) :
private void txtFilter_TextChanged(object sender, TextChangedEventArgs e)
{
CollectionViewSource.GetDefaultView((DataContext as TestViewModel).LV).Refresh();
}
Il est le filtrage ok quand je tape dans la zone de texte de recherche et listview est correctement mis à jour, mais le nombre d'enregistrements est toujours 0.
Qu'est-ce que je fais mal?
ATTEMPT2: Ci-dessous une autre tentative ne fonctionne pas. Si j'attache mon listivew à la vue déclarée en mode modèle, aucun élément n'est affiché. Si j'attache listview à LV dans la vue de modèle alors les articles sont montrés, et quand je filtre dans ma zone de recherche filtre ok, listview est mis à jour mais le nombre de rangées montrées dans la listview reste toujours à 0.
Notes:
- J'utilise .NET 3.5 Visual studio 2008.
- dois-je définir Afficher en écriture en vue du modèle parce que je ne mets pas en vue constructeur de modèle, je l'ai mis à la place dans la méthode LoadData dans modèle de vue . LoadData est appelée à partir du constructeur view code-behind.
Voir Modèle:
namespace MyTest.Example
{
public Class TestViewModel : INotifyPropertyChanged // Implementations not here to simplify the code here.
{
private ObservableCollection<DataModel> lv;
public ObservableCollection<DataModel> LV
{
get
{
return this.lv;
}
private set
{
this.lv = value;
OnPropertyChanged("LV");
}
}
public CollectionView View { get; set; }
public TestViewModel()
{
this.LV = new ObservableCollection<DataModel>();
// this.View = (CollectionView)CollectionViewSource.GetDefaultView(this.LV);
// this.View.Filter = UserFilter;
}
private string textFilter = string.Empty;
public string TextFilter
{
get
{
return this.textFilter ;
}
set
{
this.textFilter = value;
OnPropertyChanged("TextFilter");
this.View.Refresh();
}
}
private bool UserFilter(object item)
{
if (String.IsNullOrEmpty(this.TextFilter))
return true;
else
{
DataModel m = (item as DataModel);
bool result = (m.Name.IndexOf(this.TextFilter, StringComparison.OrdinalIgnoreCase) >= 0 ||
//m.Surname.IndexOf(this.TextFilter, StringComparison.OrdinalIgnoreCase) >= 0);
return result;
}
}
public void LoadData()
{
this.LV = LoadDataFromDB();
this.View = (CollectionView)CollectionViewSource.GetDefaultView(this.LV);
this.View.Filter = UserFilter;
}
} // End Class
} // End namespace
Voir le code-behing (XAML.cs):
namespace MyTest.Example
{
public Class TestView
{
public TestView()
{
InitializeComponent();
(DataContext as TestViewModel).LoadData();
}
}
}
Voir (XAML):
xmlns:vm="clr-namespace:MyTest.Example"
<!-- search textbox - filter -->
<TextBox Text="{Binding Path=TextFilter, UpdateSourceTrigger=PropertyChanged}">
<!-- label to show the number of records -->
<Label Content="{Binding Path=View.Count}" ContentStringFormat="No. Results: {0}"/>
<ListView Grid.Row="1" Grid.Column="0" ItemsSource="{Binding Path=View}" SelectionMode="Extended" AlternationCount="2">
TENTATIVE 3: Enfin j'ai le faire fonctionner. La solution est la même chose que ESSAI2 mais en faisant des changements ci-dessous:
J'ai remplacé ceci:
public CollectionView View { get; set; }
par celui-ci:
private CollectionView view;
public CollectionView View {
get
{
return this.view;
}
private set
{
if (this.view == value)
{
return;
}
this.view = value;
OnPropertyChanged("View");
}
}
Tout le reste reste le même que dans ESSAI2. Dans View View.Count et l'affectation de View en ItemsSource à ma listview fonctionne maintenant parfaitement. dans l'autre question
Ce serait beaucoup plus facile si vous étiez * en fait * en utilisant le modèle MVVM, comme votre titre l'indique. Il suffit de lier votre TextBox à CollectionViewSource.Count. Je recommande d'abord de l'adapter au modèle MVVM réel, ou si vous ne voulez pas suivre cette route, mettez à jour le 'TextBox' de' Count' sur le 'CollectionViewSource' local. –
J'utilise MVVM mais je suis totalement perdu. Qu'est-ce que collectionViewSource? Je suis nouveau dans WPF. Ma listview est attachée à une collection observablecollection. – user1624552
La toute première ligne de votre code posté utilise la valeur par défaut 'CollectionView' de' CollectionViewSource', c'est ce dont je parle. –