ListBox TwoWay связывается с SelectedItem - PullRequest
5 голосов
/ 15 декабря 2009

Я видел этот вопрос много раз и перебирал свой код снова и снова. Но когда я присваиваю своему SelectedItem -связанному свойству объект, он не обновляет выбранный элемент дисплея. Похоже, что ListBox считает, что объект, который я назначил, не является членом его элементов.

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>

Вот импл из одного из мест, где я пытаюсь установить SelectedTube - определенно происходит в основном потоке.

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

Я заметил, что SelectedTube никогда не выделялся, если я не нажимал на него вручную, но как бы игнорировал его. Но затем я хотел ScrollIntoViewCentered выбранный элемент, поэтому я добавил DependencyProperty в моем представлении, чтобы следить за SelectedItem изменениями. Первоначально обработчик выглядел так:

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

    TubeList.ScrollIntoViewCentered(TubeList.SelectedItem);
}

Но не сработало, если я установил SelectedItem через привязку. Решив, что я хочу прокрутить его, только если его нет на экране, я изменил код так:

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

Если внешне установлена ​​SelectedItem, контейнер равен нулю. Каждый раз. Я даже добавил код для проверки на нулевое значение, а затем перебрал ItemsSource в поисках соответствия имени файла, затем обновил SelectedItem, чтобы убедиться, что SelectedItem определенно является объектом в списке. Неудачно.

Это не видимость, если элемент находится на экране, он все равно не выделяется. Нужно ли реализовывать какую-то функцию равенства? Я потратил на это больше времени, чем можно было бы подумать.

спасибо.

Ответы [ 3 ]

5 голосов
/ 06 января 2010

Возможно, это также связано с тем, что ItemContainerGenerators генерируются в отдельном потоке ... (, по крайней мере, в TreeView )

Попробуйте вызвать UpdateLayout (), прежде чем задать свойство ItemContainerGenerators.

3 голосов
/ 15 декабря 2009

Ничто не выскакивает на меня, как очевидно, неправильно, но вы много замяли. Я могу только предложить вам упростить ситуацию, пока вы не найдете проблему или не получите полный нерабочий пример, который вы можете опубликовать.

1 голос
/ 06 января 2010

Вы пытались проверить хеш-код каждого объекта в источнике предметов по хеш-коду объекта, который вы пытаетесь установить? Запрос Linq вернет что-то другое.

В качестве теста, пытаясь установить SelectedTube в Items [0].

...