2008-11-06 6 views
2

J'ai ce ListBox qui est lié à une ObservableCollection. Chaque objet dans la liste implémente une interface appelée ISelectableComment synchroniser l'élément SelectedItem d'un ListBox?

public interface ISelectable : INotifyPropertyChanged 
{ 
    event EventHandler IsSelected; 
    bool Selected { get; set; } 
    string DisplayText { get; } 
} 

Je veux garder une trace de l'objet sélectionné indépendamment de la façon dont il est sélectionné. L'utilisateur peut cliquer sur la représentation de l'objet dans le ListBox mais il se peut aussi qu'un objet soit sélectionné via le code. Si l'utilisateur sélectionne un objet via la ListBox, je transtype l'élément sélectionné en ISelectable et définit la propriété Selected sur true.

ISelectable selectable = (ISelectable)e.AddedItems[0]; 
selectable.Selected = true; 

Mon problème est que lorsque je sélectionne l'objet en utilisant le code, je ne peux pas obtenir ListBox pour changer l'élément sélectionné. J'utilise un DataTemplate pour montrer l'objet sélectionné dans une couleur différente, ce qui signifie que tout est affiché correctement. Mais le ListBox a le dernier objet cliqué par l'utilisateur en tant que SelectedItem qui signifie que l'article ne peut pas être cliqué sans d'abord sélectionner un autre objet dans la liste.

Quelqu'un a eu une idée sur la façon de résoudre ce problème? Je suis sûr que je peux accomplir ce que je veux en écrivant du code personnalisé pour gérer les événements de la souris et du clavier, mais je préfère ne pas. J'ai essayé d'ajouter une propriété SelectedItem à la collection et la lier à SelectItemProperty de la ListBox mais pas de chance.

Répondre

4

Vous pouvez également effectuer cela par liaison de données ListBoxItem.IsSelected à votre propriété Selected. L'idée est de définir la liaison pour chacun des ListBoxItems à mesure qu'ils sont créés. Cela peut être fait en utilisant un style qui cible chacun des ListBoxItems générés pour le ListBox.

De cette manière, lorsqu'un élément de ListBox est sélectionné/non sélectionné, la propriété Selected correspondante sera mise à jour. De même, définir la propriété Selected dans le code sera reflété dans le ListBox

Pour que cela fonctionne, la propriété Selected doit déclencher l'événement PropertyChanged.

<List.Resources> 
    <Style TargetType="ListBoxItem"> 
     <Setter 
      Property="IsSelected" 
      Value="{Binding 
         Path=DataContext.Selected, 
         RelativeSource={RelativeSource Self}}" 
      /> 
    </Style> 
</List.Resources> 
+0

C'était exactement ce que je cherchais. Merci! –

1

Avez-vous regardé les événements SelectedItemChanged et SelectedIndexChanged de la liste?

Elles doivent être déclenchées chaque fois qu'une sélection est modifiée, quelle que soit la manière dont elle est sélectionnée.

+0

Je n'ai aucun problème lorsque je clique sur un élément dans la ListBox. Dans ce cas, j'utilise l'événement SelectionChanged. Le problème est que je veux que la ListBox mette à jour la sélection lorsque je sélectionne un élément dans la liste sous-jacente. –

0

Je pense que vous devriez déclencher l'événement propertyChanged lorsque la sélection a changé. Ajoutez ce code à l'objet qui implémente ISelectable. Vous finirez avec quelque chose comme:

private bool _Selected; 
     public bool Selected 
     { 
      get 
      { 
       return _Selected; 
      } 
      set 
      { 
       if (PropertyChanged != null)     
        PropertyChanged(this, new PropertyChangedEventArgs("Selected")); 

       _Selected = value; 
      } 
     } 

J'ai essayé le code folowing:

public ObservableCollection<testClass> tests = new ObservableCollection<testClass>(); 

     public Window1() 
     { 
      InitializeComponent(); 
      tests.Add(new testClass("Row 1")); 
      tests.Add(new testClass("Row 2")); 
      tests.Add(new testClass("Row 3")); 
      tests.Add(new testClass("Row 4")); 
      tests.Add(new testClass("Row 5")); 
      tests.Add(new testClass("Row 6")); 
      TheList.ItemsSource = tests; 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      tests[3].Selected = true; 
      TheList.SelectedItem = tests[3]; 
     } 

où TestClass implémente ISelectable.

Le est un morceau de XAML, rien d'extraordinaire:

<ListBox Grid.Row="0" x:Name="TheList"></ListBox>   
<Button Grid.Row="1" Click="Button_Click">Select 4th</Button> 

J'espère que cela aide.

Questions connexes