I can't for the life of me pre-set the selected item on a list view. The core of the problem is that the object I'm passed to be the default will not be the same instance of the object that is included in the select list. I'm using Sqlite to store my data, so each call returns newly created objects (all names have been changed to protect the guilty):
// The Widget class has a unique integer Id...
MyListView.ItemsSource = MySqlRepository.GetAllWidgets();
Widget defaultWidget = MySqlRepository.GetWidgetWithId(defaultId);
I proved this idea to myself with this code:
// Horrible brute-force method broken up so I could see each piece in the debugger...
IEnumerable<Widget> wl1 = (IEnumerable<Widget>) MyListView.ItemsSource;
List<Widget> wl2 = wl1.ToList<Widget>();
int idx = wl2.FindIndex(x => x.Id == defaultWidget.Id);
Widget listWidget = wl1[idx];
if (listWidget != defaultWidget)
{
// This means that my two objects are different instances of the same "item"
// If I set a breakpoint here, execution stops at it.
}
Ok, with me so far? I have a list of widgets, and I want to make the widget with a specific Id pre-selected when the list is first shown. (The user selected something, navigated away, and came back. I want to show the item he/she selected the last time...)
If I set MyListView.SelectedItem to defaultWidget, nothing is shown to as selected. In the debugger, SelectedItem looks like it's set to the correct item, but nothing is painted as selected.
Since I know that the object referenced by defaultWidget is not the object in the ItemsSource list, I tried brute-force finding the object in the ItemsSource list with the matching Id, and setting SelectedItem to THAT. First I put this code both in the initialization stuff in the xaml.cs:
Widget w2 = null;
foreach (Widget w in MyListView.ItemsSource)
{
if (w.Id == defaultWidget.Id)
{
SelectedItem = w;
break;
}
}
That didn't work, so I bound SelectedItem to a property (SelectAWidgetPage.xaml):
<ListView x:Name="MyListView"
CachingStrategy="RecycleElement"
SelectedItem="{Binding TheSelectedWidget, Mode=TwoWay}"
ItemsSource="{Binding TheWidgetList}" >
... and put my selection code in the setter (SelectAWidgetViewModel.cs):
private ObservableCollection<Widget> _listWidgets;
public ObservableCollection<Widget> TheWidgetList;
{
get
{
return _listWidgets;
}
}
private Widget _selectedWidget;
public Widget TheSelectedWidget
{
get
{
return _selectedWidget;
}
set
{
if (value == null)
{
_selectedWidget = null;
}
else if ((_selectedWidget == null) || (value.Id != _selectedWidget.Id))
{
foreach (Widget w in _listWidgets)
{
if (w.Id == value.Id)
{
_selectedWidget = w;
// I added this just in case it helped... it didn't. But, yes, I do implement INotifyPropertyChanged...
OnPropertyChanged("TheSelectedWidget");
break;
}
}
}
}
}
It's ugly, inefficient, brute-force code that should work. It does not. STILL, when I return to this page, the default item is not selected.
Help? I'm stumped at this point.
Thanks in advance for any insight you can provide!