2009-12-15 7 views
5

Ich habe diese Frage mehrmals gestellt und bin immer wieder über meinen Code gestolpert. Aber wenn ich meinem Objekt SelectedItem -bound ein Objekt zuweisen, wird das ausgewählte Element des Displays nicht aktualisiert. Es scheint, dass die ListBox denkt, dass das Objekt, das ich zuweisen, kein Mitglied seiner Elemente ist.ListBox TwoWay Bindung an 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> 

Hier ist der impl von einem der Orte, an denen ich versuche, SelectedTube zu setzen - tritt auf jeden Fall auf dem Haupt-Thread.

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

Ich war zu bemerken, dass die SelectedTube nie, wenn ich auf ihn manuell markiert wurde geklickt, aber irgendwie es ignoriert. Aber dann wollte ich ScrollIntoViewCentered das ausgewählte Element, also fügte ich eine DependencyProperty in meiner Sicht auf SelectedItem Änderungen zu sehen. Der Handler sah zunächst wie so:

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

    TubeList.ScrollIntoViewCentered(TubeList.SelectedItem); 
} 

Aber hat nicht funktioniert, wenn ich die SelectedItem durch meine Bindung eingestellt. wenn es nicht auf dem Bildschirm, änderte ich den Code dieses Nach der Entscheidung, ich es nur blättern wollte:

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); 
} 

Wenn SelectedItem extern eingestellt, Container ist null. Jedes Mal. Ich habe sogar Code hinzugefügt, um nach Null zu suchen, und dann iteriere über ItemsSource auf der Suche nach einem passenden Dateinamen und aktualisiere dann SelectedItem, um sicherzustellen, dass SelectedItem definitiv ein Objekt in der Listbox ist. Kein Glück.

Es ist keine Sichtbarkeit Sache, wenn das Element auf dem Bildschirm ist, wird es immer noch nicht markiert. Muss ich eine Art Gleichheitsfunktion implementieren? Ich habe mehr Zeit verschwendet, als man vielleicht für möglich hält.

danke.

+0

Ich konnte dies mit dem, was wir von Ihrem Code sehen, nicht reproduzieren. Ich habe eine Dummy-Klasse für TubeViewModel erstellt und den gesamten von Ihnen geposteten Code verwendet, und es hat wie erwartet funktioniert. Etwas muss anderswo weitergehen. –

+0

Vielen Dank, Ben und Kent. Ich mache eine Weile Urlaub, das muss warten. – Thomas

Antwort

5

Vielleicht ist dies auch auf die Tatsache, dass ItemContainerGenerators in einem separaten Thread erzeugt werden ... (at least in the TreeView)

Versuchen UpdateLayout() aufrufen, bevor Sie bitten, die ItemContainerGenerators Eigenschaft.

+0

Ich verstehe nicht, warum das notwendig ist, aber ich bin froh, dass es ist. Danke vielmals. – Thomas

3

Nichts springt auf mich als offensichtlich falsch, aber Sie haben viel beschönigt. Ich kann nur vorschlagen, dass Sie die Dinge vereinfachen, bis Sie entweder das Problem gefunden haben oder ein komplett funktionsloses Beispiel haben, das Sie posten können.

1

Haben Sie versucht, den Hashcode jedes Objekts in der Itemsource mit dem Hashcode des Objekts zu vergleichen, das Sie einstellen möchten? Die Linq-Abfrage wird etwas anderes zurückgeben.

Als Test versuchen, SelectedTube auf Elemente [0] zu setzen.