2009-12-15 9 views
5

J'ai vu cette question posée plusieurs fois et j'ai parcouru mon code encore et encore. Mais lorsque j'affecte à ma propriété SelectedItem avec un objet, elle ne met pas à jour l'élément sélectionné de l'affichage. Il semble que le ListBox pense que l'objet que j'attribue n'est pas un membre de ses éléments.ListBox TwoWay lié à SelectedItem

public class MainViewModel : ViewModelBase 
{ 
    //... 
    public SortedObservableCollection<TubeViewModel> Items { get; private set; } 
    public TubeViewModel SelectedTube { //get, set, propertychanged, etc. } 
} 

<ListBox x:Name="TubeList" 
     Margin="10" 
     ItemsSource="{Binding Items}" 
     ItemTemplate="{StaticResource TubeTemplate}" 
     SelectedItem="{Binding SelectedTube, Mode=TwoWay}" 
     SelectionMode="Single" 
     VirtualizingStackPanel.IsVirtualizing="False"> 
</ListBox> 

Voici le impl d'un des endroits où je tente de mettre SelectedTube - se produit certainement sur le thread principal.

var match = 
    from t in Items 
    where t.Model.DataFileName == filename 
    select t; 
if (match.Any()) 
    SelectedTube = match.First(); 

Je notais que le SelectedTube n'a jamais été mis en évidence à moins que je cliqué manuellement, mais sorte de ignora. Mais alors je voulais ScrollIntoViewCentered l'élément sélectionné, donc j'ai ajouté un DependencyProperty à mon avis pour voir SelectedItem changements. Le gestionnaire avait l'air d'abord comme ceci:

private void OnSelectedItemChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) 
{ 
    if (TubeList.SelectedItem == null) 
     return; 

    TubeList.ScrollIntoViewCentered(TubeList.SelectedItem); 
} 

Mais ne fonctionnait pas si je mis le SelectedItem par mon engagement. Après avoir décidé que je voulais faire défiler que si elle était pas à l'écran, j'ai changé le code à ceci:

private void OnSelectedItemChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) 
{ 
    if (TubeList.SelectedItem == null) 
     return; 

    var container = TubeList.ItemContainerGenerator.ContainerFromItem(TubeList.SelectedItem) as FrameworkElement; 

    if(!container.IsVisible) 
     TubeList.ScrollIntoViewCentered(TubeList.SelectedItem); 
} 

Si SelectedItem est fixé à l'extérieur, le conteneur est nul. À chaque fois. J'ai même ajouté du code pour vérifier null, puis itérer sur le ItemsSource en recherchant une correspondance de nom de fichier, puis mettre à jour SelectedItem pour m'assurer que SelectedItem était définitivement un objet dans la liste. Pas de chance.

Ce n'est pas une question de visibilité, si l'élément est à l'écran, il ne ressort toujours pas. Dois-je mettre en place une sorte de fonction d'égalité? J'ai perdu plus de temps que l'on pourrait penser possible à ce sujet.

merci.

+0

Je n'ai pas pu reproduire ceci avec ce que nous voyons de votre code. J'ai fait une classe factice pour TubeViewModel et utilisé tout votre code posté et cela a fonctionné comme prévu. Quelque chose doit se passer ailleurs. –

+0

Merci beaucoup, Ben et Kent. Je pars en vacances pour un moment, cela devra attendre. – Thomas

Répondre

5

Peut-être que cela est également lié au fait que ItemContainerGenerators sont générés dans un thread séparé ... (at least in the TreeView)

Essayez d'appeler UpdateLayout() avant de vous demander la propriété ItemContainerGenerators.

+0

Je ne comprends pas pourquoi c'est nécessaire, mais je suis content que ce soit. Merci beaucoup. – Thomas

3

Rien ne me saute aux yeux comme si c'était manifestement faux, mais vous avez beaucoup réfléchi. Je ne peux que vous suggérer de simplifier les choses jusqu'à ce que vous trouviez le problème, ou que vous ayez un exemple complet de non-travail que vous pouvez publier.

1

Avez-vous essayé de vérifier le code de hachage de chaque objet dans la source d'articles par rapport au code de hachage de l'objet que vous essayez de définir? La requête Linq retournera quelque chose de différent.

En tant que test essayant de définir le SelectedTube à Items [0].

Questions connexes