2010-12-17 12 views
8

Tengo un problema al utilizar el enlace bidireccional con un listpicker. Puedo establecer el valor usando C# pero no en el SelectedItem=".." en xaml. El enlace está devolviendo el valor correcto (y es un valor en el listpicker) ya que lo he enviado un mensaje de texto asignando el texto a un bloque de texto.Problema de configuración de enlace bidireccional

Cuando se carga la página, la unión utilizados en la ListPicker provoca una System.ArgumentOutOfRangeException

El código que estoy utilizando para configurarlo es:

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

Y en el 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> 

El StaticResource AppSettings es un recurso de un archivo .cs separado.

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

Gracias de antemano

+0

¿Qué quiere decir cuando escribe '{StaticResource AppSettings}'? ¿Es un nombre de 'recurso' definido en algún lugar en' XAML' o 'clase estática'? – decyclone

+0

Sí, lo siento, olvidé mencionar que AppSettings es un archivo de clase separado – Jamie

+0

¿Es una clase estática? ¿Está confundiendo '{x: Static AppSettings.WeekBeginsSetting}' con su enlace actual? Porque Silverlight no admite '{x: Static}'. – decyclone

Respuesta

5

Utilicé Reflector para encontrar el origen de esta excepción. En ListPicker.cs se anula el siguiente método.

protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) 

En este método la línea siguiente hará que la excepción si SelectedItem se establece y SelectedIndex es -1 (que lo es a menos que se establece antes de que sea cargado). Si SelectedItem no está configurado, esta línea nunca se alcanza (por lo tanto, no es una excepción).

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

Para solucionar esto (hasta que se solucionen) tengo algunas sugerencias.

Solución 1

Si conoce el índice de inicio que será producido por el TwoWay vinculante entonces se puede establecer la propiedad SelectedIndex también y el TwoWay Encuadernación trabajará

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

Solución 2

Utilice el evento Cargado y establezca el Enlace desde allí en su lugar

<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

thx para una vista detallada de esto. Creo que iré con la solución # 2. – Stan

0

¿Estás disparando la propiedad relevante cambió acontecimientos?

Asegúrese de que SelectedItem pueda tener un enlace bidireccional. Si no, intente definir un ItemContainerStyle y enlace la propiedad IsSelected con la propiedad correspondiente de su objeto. Obtener el elemento seleccionado se vuelve trivial.

+0

Vaya, olvidé mencionar el problema que estoy teniendo cuando configuro listpicker arroja 'System.ArgumentOutOfRangeException' – Jamie

0

Si AppSettings es una colección, esto no va a funcionar. Debe vincular SelectedItem a un valor escalar y desafortunadamente el "Silverlight 3.7" en WP7 no es compatible con indexadores en enlaces.

También, por favor no utilice excepciones como el control de flujo en su programa, en vez de hacer algo como esto:

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

Gracias, puedo hacer que SelectedIndex funcione, pero solo resalta el elemento y no lo muestra cuando el selector de lista está inactivo: muestra el primer valor en el selector de lista. – Jamie

0

En lugar de utilizar la unión simplemente puse el SelectedItem cuando la página carga y se utiliza un evento SelectionChanged controlador para actualizar el valor sin confirmación (con un botón de guardar).

Cuestiones relacionadas