2010-12-17 7 views
8

Ich habe ein Problem mit Zwei-Wege-Bindung mit einem Listpicker. Ich bin in der Lage, den Wert mit C#, aber nicht in der SelectedItem=".." in Xaml. Die Bindung gibt den richtigen Wert zurück (und ist ein Wert im Listenpicker), da ich sie durch Textvergabe an einen Textblock gesendet habe.Zwei-Wege-Bindung Einstellungen Problem

Wenn die Seite geladen, die auf der listpicker verwendete Bindung verursacht eine System.ArgumentOutOfRangeException

Der Code ich es einstellen verwende ist:

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

Und in der 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> 

Die StaticResource AppSettings ist eine Ressource aus einer separaten CS-Datei.

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

Vielen Dank im Voraus

+0

Was meinen Sie, wenn Sie '{StaticResource AppSettings}' schreiben? Ist es ein Name von 'Ressource', der irgendwo in' XAML' oder einer 'statischen Klasse' definiert ist? – decyclone

+0

Ja Entschuldigung, ich habe vergessen, AppSettings zu erwähnen ist eine separate Klassendatei – Jamie

+0

Ist es eine statische Klasse? Verwechseln Sie '{x: Static AppSettings.WeekBeginsSetting}' mit Ihrer aktuellen Bindung? Weil Silverlight '{x: Static}' nicht unterstützt. – decyclone

Antwort

5

Ich habe Reflektor verwendet, um die Quelle dieser Ausnahme zu finden. In ListPicker.cs wird die folgende Methode überschrieben.

protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) 

Bei diesem Verfahren führt dazu, dass die folgende Zeile die Ausnahme, wenn SelectedItem gesetzt und SelectedIndex ist -1 (was es ist, wenn es gesetzt ist, bevor es geladen wird). Wenn SelectedItem nicht gesetzt ist, wird diese Zeile nie erreicht (daher keine Ausnahme).

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

Um dies zu umgehen (bis sie das behoben) habe ich einige Vorschläge.

Problemumgehung 1

Wenn Sie wissen, den Startindex, der durch die TwoWay Bindung erzeugt wird, dann können Sie auch die SelectedIndex-Eigenschaft und die TwoWay wird Binding arbeiten

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

Umgehung 2

Verwenden Sie das Loaded-Ereignis und legen Sie stattdessen die Bindung von dort

fest
<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 für den detaillierten Blick auf diese. Ich denke, ich werde mit Workaround # 2 gehen. – Stan

0

feuern Sie die relevante Eigenschaft Ereignisse verändert?

Stellen Sie sicher, dass SelectedItem eine bidirektionale Bindung haben kann.Wenn Sie nicht versuchen, einen ItemContainerStyle zu definieren und die IsSelected-Eigenschaft an eine entsprechende Eigenschaft Ihres Objekts zu binden, wird das ausgewählte Element trivial.

+0

Hoppla, ich habe vergessen, das Problem zu erwähnen, das ich habe, wenn ich den listpicker setze, wirft es eine 'System.ArgumentOutOfRangeException' – Jamie

0

Wenn AppSettings eine Sammlung ist, wird dies nicht funktionieren. Sie müssen SelectedItem an einen Skalarwert binden und leider unterstützt "Silverlight 3.7" auf WP7 keine Indexer in Bindungen.

Auch benutzen Sie bitte nicht Ausnahmen als Flusskontrolle in Ihrem Programm, sondern etwas tun:

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

Danke, ich kann SelectedIndex zur Arbeit bringen, aber es hebt nur das Element hervor und zeigt es nicht, wenn der Listenwähler ist inaktiv - zeigt stattdessen den ersten Wert in der Listenauswahl an. – Jamie

0

Anstelle der Verwendung von Bindung Ich habe einfach die SelectedItem, wenn die Seite geladen und verwendet, um ein selection Ereignis Handler, um den Wert ohne Bestätigung zu aktualisieren (mit einer Schaltfläche zum Speichern).