Updating ObservableCollection bound to Pivot crashes for SelectedIndex >= 2 (wp7)
I have an observableCollection bound to a pivot control in my UI. When I try to update the collection (clear() items and recreate) everything works fine unless t开发者_C百科he selectedIndex of the pivot control is bigger or equal to 2.
In that case I get an ArgumentOutOfRange exception when I try to call Add() to the observable collection. It is very strange.
I tried creating a new observable collection and then Add() items there, this seems to work but I doesn't refresh the UI unless I call my update function twice.
What can be wrong? Is this a bug?
This is a known issue.
Unhandled Exception When Setting Pivot Control SelectedItem/SelectedIndex Property to 3rd Pivot Item (WP7)
Not deferring navigation/(binding?) to the loaded event is a workaround.
You have probably alreade solved it but here is what I did. As mentioned before this is a known "bug"/limitation. You can however set the SelectedIndex in the Loaded event for the page.
See here: http://christian-helle.blogspot.com/2011/02/working-around-pivot-selectedindex.html
This helped me and it works just fine now =)
To try and save load and performacne overhead, the framework only loads the currently displayed pivot and the ones either side. The other items are delay loaded when the neighbouring item is displayed. As a consequence of this you can experience issues when trying to set the SelectedItem to an item which hasn't been loaded or the page hasn't finished loading fully.
If you can share some code to demonstrate what you're trying to do we may be able to provide some more specific help.
As mentioned. The Pivot control is optimised to not load all the panels. If you are trying what I think you're trying, then I would suggest you switch to a Panorama Control which initalises all the PanoramaItems.
I'm going to try the fix suggested @Jimmy Engtröm. However, I've also been able to work around this by waiting until the Load has occurred.
<controls:Pivot x:Name="pivotCtrl" Title="{Binding ApplicationTitle}"
Loaded="OnPivotControlLoaded" Opacity="1">
And in the page's code behind:
private void OnPivotControlLoaded(object sender, RoutedEventArgs e)
{
// Restore the Pivot control's SelectedIndex
if (State.ContainsKey(SelectedPivotIndexKey))
{
pivotCtrl.SelectedIndex = State.Get<int>(SelectedPivotIndexKey);
}
myStoryboard.Begin();
}
Now, why the Storyboard? Well, when you wait until Load, you will see the first pivot and that's lame. So the Storyboard does a quick fade-in...just enough to disguise the fix. I tried just setting Visibility, but that would crash the app. Also note that, for design purposes, I leave Opacity set to 1 in the pivot control's XAML. Here's the Storyboard:
<Storyboard x:Name="myStoryboard">
<DoubleAnimation
Storyboard.TargetName="pivotCtrl"
Storyboard.TargetProperty="Opacity"
From="0.0" To="1.0" Duration="0:0:01"
/>
</Storyboard>
Here are the helper functions (placed in a separate class file and referenced, e.g. using MyApp.Helpers and the class file needs to reference System.Collections.Generic)
public static T Get<T>(this IDictionary<string, object> dictionary, string key)
{
return (T)dictionary[key];
}
public static void AddOrReplace<T>(this IDictionary<string, T> dictionary, string key, T item)
{
if (dictionary.ContainsKey(key))
dictionary.Remove(key);
dictionary.Add(key, item);
}
Again, it's not the greatest fix but it works alright and the fade-in is actually something I might employ elsewhere.
精彩评论