Reputation: 4960
I am having a problem using two way binding with a listpicker. I am able to set the value using c# but not in the SelectedItem=".."
in xaml. The binding is returning the correct value (and is a value in the listpicker) as i have texted it by assigning the text to a textblock.
When the page loads, the binding used on the listpicker causes a System.ArgumentOutOfRangeException
The code i am using to set it is:
// Update a setting value. If the setting does not exist, add the setting.
public bool AddOrUpdateValue(string key, Object value)
{
bool valueChanged = false;
try
{
// If new value is different, set the new value
if (settingsStorage[key] != value)
{
settingsStorage[key] = value;
valueChanged = true;
}
}
catch (KeyNotFoundException)
{
settingsStorage.Add(key, value);
valueChanged = true;
}
catch (ArgumentException)
{
settingsStorage.Add(key, value);
valueChanged = true;
}
catch (Exception e)
{
Console.WriteLine("Exception occured whilst using IsolatedStorageSettings: " + e.ToString());
}
return valueChanged;
}
// Get the current value of the setting, if not found, set the setting to default value.
public valueType GetValueOrDefault<valueType>(string key, valueType defaultValue)
{
valueType value;
try
{
value = (valueType)settingsStorage[key];
}
catch (KeyNotFoundException)
{
value = defaultValue;
}
catch (ArgumentException)
{
value = defaultValue;
}
return value;
}
public string WeekBeginsSetting
{
get
{
return GetValueOrDefault<string>(WeekBeginsSettingKeyName, WeekBeginsSettingDefault);
}
set
{
AddOrUpdateValue(WeekBeginsSettingKeyName, value);
Save();
}
}
And in the xaml:
<toolkit:ListPicker x:Name="WeekStartDay"
Header="Week begins on"
SelectedItem="{Binding Source={StaticResource AppSettings},
Path=WeekBeginsSetting,
Mode=TwoWay}">
<sys:String>monday</sys:String>
<sys:String>sunday</sys:String>
</toolkit:ListPicker>
The StaticResource AppSettings
is a resource from a seperate .cs file.
<phone:PhoneApplicationPage.Resources>
<local:ApplicationSettings x:Key="AppSettings"></local:ApplicationSettings>
</phone:PhoneApplicationPage.Resources>
Thanks in advance
Upvotes: 8
Views: 2700
Reputation: 84647
I used Reflector to find the source of this exception. In ListPicker.cs the following method is overridden.
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
In this method the following line will cause the exception if SelectedItem is set and SelectedIndex is -1 (which it is unless it's set before it's loaded). If SelectedItem isn't set this line is never reached (hence no exception).
else if (!object.Equals(base.get_Items().get_Item(this.SelectedIndex), this.SelectedItem))
To work around this (until they get this fixed) I have some suggestions.
Workaround 1
If you know the starting index which will be produced by the TwoWay binding then you can set the SelectedIndex property as well and the TwoWay Binding will work
<toolkit:ListPicker x:Name="WeekStartDay"
Header="Week begins on"
SelectedItem="{Binding Source={StaticResource AppSettings},
Path=WeekBeginsSetting,
Mode=TwoWay}"
SelectedIndex="1">
<sys:String>monday</sys:String>
<sys:String>sunday</sys:String>
</toolkit:ListPicker>
Workaround 2
Use the Loaded event and set the Binding from there instead
<toolkit:ListPicker x:Name="WeekStartDay"
Header="Week begins on"
Loaded="WeekStartDay_Loaded">
<sys:String>monday</sys:String>
<sys:String>sunday</sys:String>
</toolkit:ListPicker>
private void WeekStartDay_Loaded(object sender, RoutedEventArgs e)
{
Binding binding = new Binding();
binding.Source = this.Resources["AppSettings"] as ApplicationSettings;
binding.Path = new PropertyPath("WeekBeginsSetting");
binding.Mode = BindingMode.TwoWay;
WeekStartDay.SetBinding(ListPicker.SelectedItemProperty, binding);
}
Upvotes: 5
Reputation: 4960
Instead of using binding I simply set the selecteditem when the page loaded and used a selectionchanged event handler to update the value without confirmation (having a save button).
Upvotes: 0
Reputation: 42227
If AppSettings is a collection then this is not going to work. You need to bind SelectedItem
to a scalar value and unfortunately the "Silverlight 3.7" on WP7 doesn't support indexers in bindings.
Also, please don't use exceptions as flow control in your program, instead do something like this:
try
{
// If new value is different, set the new value
if(!settingsStorage.ContainsKey(key))
{
settingsStorage.Add(key, value);
valueChanged = true;
}
else if(settingsStorage[key] != value)
{
settingsStorage[key] = value;
valueChanged = true;
}
}
catch (Exception e)
{
Console.WriteLine("Exception occured whilst using IsolatedStorageSettings: " + e.ToString());
}
Upvotes: 0
Reputation: 665
Are you Firing the relevant property changed events?
Make sure that SelectedItem can have a two way binding.If not then try defining an ItemContainerStyle and bind the IsSelected property to a corresponding property on your object.Getting the selected item then becomes trivial.
Upvotes: 0