2 votes

Filtrage de ComboBox.ItemsSource

J'essaie de faire un ComboBox filtrer son ItemsSource sur la base d'un FilterValue liée à son Text ; le contrôle se trouve à l'intérieur du CellEditingTemplate d'un DataGrid qui est lui-même à l'intérieur d'un DataTemplate . Les éléments mettent tous en œuvre un ICodeName qui garantit qu'il y a une Code et un Name et j'utilise avec succès une propriété ItemTemplate qui en tire parti.

Ainsi, le contexte d'une DataGridRow est un Foo une classe de modèle de vue qui implémente INotifyPropertyChanged et expose un Bars qui est une ICollectionView ("SuggestionBox" est un contrôle d'utilisateur héritant de ComboBox ) :

<DataGridTemplateColumn Header="Bar">
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <local:SuggestionBox Text="{Binding FilterValue, UpdateSourceTrigger=PropertyChanged}"
                                 ItemsSource="{Binding Bars, UpdateSourceTrigger=PropertyChanged}"
                                 ItemTemplate="{StaticResource CodeNameDropdownTemplate}">
            </local:SuggestionBox>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

La classe d'éléments de la rangée de grille ( Foo ) les expose :

private ICollectionView _bars;
public ICollectionView Bars
{
    get { return _bars; }
    set
    {
        if (_bars != value)
        {
            _bars = value;
            _bars.Filter = FilterBars;
            OnPropertyChanged();
        }
    }
}

private bool FilterBars(object obj)
{
    var item = (ICodeName)obj;
    return string.IsNullOrEmpty(FilterValue) 
        || item.Code.Contains(FilterValue) 
        || item.Name.Contains(FilterValue);
}

private string _filterValue;
public string FilterValue
{
    get
    {
        return _filterValue;
    }
    set
    {
        if (_filterValue != value)
        {
            _filterValue = value;
            OnPropertyChanged();
            Bars.Refresh();
        }
    }
}

Quand j'exécute le programme, je peux voir la Bars dans la liste déroulante ; lorsque je tape dans la "boîte à idées", un point d'arrêt défini dans la fenêtre de l'outil d'évaluation de la sécurité est activé. FilterValue le passeur est touché - cependant FilterBars n'est jamais invoquée.

Qu'est-ce que je fais de mal ?

2voto

redcurry Points 1270

Lorsque j'ai essayé quelque chose de similaire, en utilisant un CollectionView a en fait généré un avertissement pour moi :

System.Windows.Data Warning: 53 : Using CollectionView directly is not fully supported.  The basic features work, although with some inefficiencies, but advanced features may encounter known bugs.  Consider using a derived class to avoid these problems.

Au lieu d'instancier un CollectionView directement, vous pouvez faire ce qui suit :

Bars = CollectionViewSource.GetDefaultView(codeNames);

Cela va instancier un ListCollectionView qui dérive de CollectionView . Au fait, codeNames est juste la variable que j'ai donnée à votre ObservableCollection<ICodeName> .

Enfin, même si vous rafraîchissez l'écran du ICollectionView dans le FilterValue setter, vous devez toujours indiquer à WPF de rafraîchir sa vue. En d'autres termes, vous devez élever PropertyChanged sur Bars .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X