Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two way binding settings problem

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

like image 526
Jamie Avatar asked Dec 17 '10 16:12

Jamie


People also ask

What is 2 way data binding android?

Two-way Data Binding is a technique of binding your objects to your XML layouts so that the layout can send data to your binding object. This is compared to a “traditional” or “one-way” Data Binding setup, where data would only move from your binding object to the layout.

What is 2 way data binding?

Two-way binding gives components in your application a way to share data. Use two-way binding to listen for events and update values simultaneously between parent and child components.

How to use two way binding?

Two-way data binding refers to sharing data between a component class and its template. If you change data in one place, it will automatically reflate at the other end. For example, if you change the value of the input box, then it will also update the value of the attached property in a component class.

How to achieve two way binding in Angular?

Note: For two way data binding, we have to enable the ngModel directive. It depends upon FormsModule in angular/forms package, so we have to add FormsModule in imports[] array in the AppModule.


1 Answers

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);
}
like image 167
Fredrik Hedblad Avatar answered Oct 05 '22 03:10

Fredrik Hedblad