开发者

ListBox TwoWay bind to SelectedItem

I've seen this quest开发者_JAVA技巧ion asked numerous times and have gone over my code over and over. But when I assign to my SelectedItem-bound property with an object, it does not update the display's selected item. It appears that the ListBox thinks the object I assign is not a member of its items.

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>

Here's the impl from one of the places where I try to set SelectedTube - definitely occurs on the main thread.

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

I was noticing that the SelectedTube was never highlighted unless I manually clicked on it, but kind of ignored it. But then I wanted to ScrollIntoViewCentered the selected item, so I added a DependencyProperty in my view to watch for SelectedItem changes. The handler initially looked like so:

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

    TubeList.ScrollIntoViewCentered(TubeList.SelectedItem);
}

But didn't work if I set the SelectedItem through my binding. After deciding I wanted to only scroll it if it was not on screen, I changed the code to this:

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

If SelectedItem is externally set, container is null. Every time. I even added code to check for null and then iterate over the ItemsSource looking for a filename match, then update SelectedItem to make sure SelectedItem was definitely an object in the listbox. No luck.

It's not a visibility thing, if the item is on screen, it still doesn't highlight. Do I need to implement some sort of equality function? I've wasted more time than one might think possible on this.

thanks.


Maybe this is also related to the fact that ItemContainerGenerators are generated in a separate thread... (at least in the TreeView)

Try calling UpdateLayout() before you ask the ItemContainerGenerators property.


Nothing jumps out at me as obviously wrong, but you've glossed over a lot. I can only suggest you simplify things until you either find the problem, or have a complete non-working example that you can post.


Have you tried checking the hashcode of each object in the itemsource against the hashcode of the object you are trying to set? The Linq query will return something different.

As a test trying setting the SelectedTube to Items[0].

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜