I've seen this question 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].
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With