2009-12-15 11 views
5

He visto esta pregunta varias veces y he revisado mi código una y otra vez. Pero cuando asigno a mi propiedad SelectedItem -bound con un objeto, no actualiza el elemento seleccionado de la pantalla. Parece que el ListBox cree que el objeto que asigno no es miembro de sus elementos.ListBox TwoWay se unen a 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> 

Aquí está la impl de uno de los lugares en los que intenta establecer SelectedTube - definitivamente se produce en el hilo principal.

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

notaba que el SelectedTube Nunca se destacó menos que he hecho clic en él de forma manual, pero un poco ignoré. Pero luego quería ScrollIntoViewCentered el artículo seleccionado, así que agregué un DependencyProperty en mi vista para ver los cambios de SelectedItem. El manejador inicialmente parecía así:

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

    TubeList.ScrollIntoViewCentered(TubeList.SelectedItem); 
} 

Pero no funcionó si fijo el SelectedItem a través de mi unión. Después de decidir que quería sólo para desplazarse si no estaba en la pantalla, he cambiado el código para esto:

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á impuesta externamente, contenedor es nula. Cada vez. Incluso agregué código para verificar nulo y luego iterar sobre ItemsSource buscando una coincidencia de nombre de archivo, luego actualizar SelectedItem para asegurarme de que SelectedItem era definitivamente un objeto en el cuadro de lista. Sin suerte.

No es una cuestión de visibilidad, si el elemento está en la pantalla, aún no resalta. ¿Debo implementar algún tipo de función de igualdad? He perdido más tiempo del que uno podría pensar posible en esto.

gracias.

+0

No pude reproducir esto con lo que vemos de su código. Hice una clase ficticia para TubeViewModel y usé todo el código publicado y funcionó como se esperaba. Algo debe estar pasando en otro lugar. –

+0

Muchas gracias, Ben y Kent. Me voy de vacaciones por un tiempo, esto tendrá que esperar. – Thomas

Respuesta

5

Tal vez esto también está relacionado con el hecho de que ItemContainerGenerators se generan en un hilo separado ... (at least in the TreeView)

Trate de llamar UpdateLayout() antes de pedir a la propiedad ItemContainerGenerators.

+0

No entiendo por qué es necesario, pero estoy feliz de que sea así. Gracias una tonelada. – Thomas

3

Nada salta a la vista como obviamente erróneo, pero ha pasado por alto mucho. Solo puedo sugerirle que simplifique las cosas hasta que encuentre el problema o tenga un ejemplo completo que no funcione y que pueda publicar.

1

¿Ha intentado comprobar el hashcode de cada objeto en el origen de elementos contra el código hash del objeto que está intentando establecer? La consulta de Linq devolverá algo diferente.

Como prueba, intente configurar el SelectedTube en Elementos [0].

Cuestiones relacionadas