Problem with two-way binding settings

I have a problem using two way binding to listpicker. I can set the value using C #, but not in SelectedItem=".." in xaml. Binding returns the correct value (and is the value in listpicker) since I wrote it by assigning text to a text block.

When the page loads, the binding used in listpicker raises a System.ArgumentOutOfRangeException

The code I use to install it:

  // 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 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> 

StaticResource AppSettings is a resource from a separate .cs file.

 <phone:PhoneApplicationPage.Resources> <local:ApplicationSettings x:Key="AppSettings"></local:ApplicationSettings> </phone:PhoneApplicationPage.Resources> 

Thanks in advance

+8
c # windows-phone-7 silverlight xaml
source share
4 answers

I used Reflector to find the source of this exception. The following method is overridden in ListPicker.cs.

 protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) 

In this method, the next line will throw an exception if SelectedItem is selected, and SelectedIndex is -1 (which it is if it is not installed before loading it). If SelectedItem is not set, this line will never be reached (hence, there will be no exception).

 else if (!object.Equals(base.get_Items().get_Item(this.SelectedIndex), this.SelectedItem)) 

To get around this (until they are fixed), I have some suggestions.

Workaround 1

If you know the starting index that the TwoWay binding will create, you can also set the SelectedIndex property, 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 Binding 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); } 
+5
source share

Are you shooting modified events of the corresponding property?

Make sure SelectedItem can have two-way binding. If then do not try to define ItemContainerStyle and bind the IsSelected property to the corresponding property of the object. Getting the selected item becomes trivial.

0
source share

If AppSettings is a collection, this will not work. You need to bind SelectedItem to a scalar value and, unfortunately, β€œSilverlight 3.7” on WP7 does not support indexers in bindings.

Also, do not 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()); } 
0
source share

Instead of using binding, I simply set the selected item when the page loads and uses the selectionchanged handler to update the value without confirmation (with a save button).

0
source share

Source: https://habr.com/ru/post/650246/


All Articles