Проблема двухстороннего связывания настроек - PullRequest
8 голосов
/ 17 декабря 2010

У меня проблема с использованием двухсторонней привязки со списком. Я могу установить значение с помощью c #, но не в SelectedItem=".." в xaml. Привязка возвращает правильное значение (и это значение в списке выбора), поскольку я отправил ему текстовое сообщение, назначив текст текстовому блоку.

Когда страница загружается, привязка, используемая в списке выбора, вызывает System.ArgumentOutOfRangeException

Код, который я использую для его установки:

    // 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();
        }
    }

А в 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 - это ресурс из отдельного файла .cs.

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

Заранее спасибо

Ответы [ 4 ]

5 голосов
/ 26 декабря 2010

Я использовал Reflector, чтобы найти источник этого исключения. В ListPicker.cs следующий метод переопределен.

protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)

В этом методе следующая строка вызовет исключение, если SelectedItem установлен, а SelectedIndex равен -1 (что не происходит, если он не установлен перед загрузкой). Если SelectedItem не установлен, эта строка никогда не достигается (следовательно, не исключение).

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

Чтобы обойти это (пока они не исправят это), у меня есть несколько предложений.

Обходной путь 1

Если вы знаете начальный индекс, который будет создан привязкой TwoWay, то вы также можете установить свойство SelectedIndex, и привязка TwoWay будет работать

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

Обходной путь 2

Используйте событие Loaded и установите вместо него Binding

<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);
}
0 голосов
/ 17 декабря 2010

Если AppSettings является коллекцией, это не сработает.Вам необходимо привязать SelectedItem к скалярному значению, и, к сожалению, «Silverlight 3.7» на WP7 не поддерживает индексаторы в привязках.

Также, пожалуйста, не используйте исключения как управление потоком в вашей программе, вместо этогосделать что-то вроде этого:

    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 голосов
/ 19 декабря 2010

Вместо использования привязки я просто устанавливаю selecteditem, когда страница загружается, и использовал обработчик события selectionbreak, чтобы обновить значение без подтверждения (с кнопкой сохранения).

0 голосов
/ 17 декабря 2010

Запускаете ли вы соответствующие события измененного свойства?

Убедитесь, что SelectedItem может иметь двустороннюю привязку. Если нет, тогда попробуйте определить ItemContainerStyle и связать свойство IsSelected с соответствующим свойством вашего объекта.выбранный элемент становится тривиальным.

...