2015-11-22 2 views
5

Dies ist eine Fortsetzung von an earlier question.UWP reflektieren CombBox ausgewähltes Element geladen von Einstellungen durch Bindung

Für einige App-Einstellungen möchte ich eine ComboBox verwenden, um eine Option auszuwählen. Ich kann die ausgewählte Option in (Roaming) Einstellungen speichern und erneut laden. Die geladene Option wird ordnungsgemäß im TextBlock angezeigt, aber die ComboBox zeigt ein Leerzeichen. Wie kann ich auch die geladene aktuell ausgewählte Option in der ComboBox wiedergeben?

Dies ist die XAML:

<Page 
x:Class="ComboBoxTest.MainPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:local="using:ComboBoxTest" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:converter="using:ComboBoxTest.Converter" 
mc:Ignorable="d"> 

<Page.Resources> 
    <converter:ComboBoxItemConvert x:Key="ComboBoxItemConvert" /> 
</Page.Resources> 


<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <StackPanel> 
     <ComboBox 
      Name="ComboBox" 
      ItemsSource="{x:Bind ComboBoxOptions}" 
      SelectedItem="{x:Bind SelectedComboBoxOption, Mode=TwoWay, Converter={StaticResource ComboBoxItemConvert}}" 
      SelectedValuePath="ComboBoxOption" 
      DisplayMemberPath="ComboBoxHumanReadableOption" 
      Header="ComboBox" > 
     </ComboBox> 
     <TextBlock Name="BoundTextblock" Text="{x:Bind SelectedComboBoxOption.ComboBoxOption, Mode=OneWay}"/> 
    </StackPanel> 
</Grid> 

Und das ist die hinter Code:

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.IO; 
using System.Linq; 
using System.Runtime.InteropServices.WindowsRuntime; 
using System.Xml.Serialization; 
using Windows.Foundation; 
using Windows.Foundation.Collections; 
using Windows.Storage; 
using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 
using Windows.UI.Xaml.Controls.Primitives; 
using Windows.UI.Xaml.Data; 
using Windows.UI.Xaml.Input; 
using Windows.UI.Xaml.Media; 
using Windows.UI.Xaml.Navigation; 

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 

namespace ComboBoxTest 
{ 
/// <summary> 
/// An empty page that can be used on its own or navigated to within a Frame. 
/// </summary> 
public sealed partial class MainPage : Page, INotifyPropertyChanged 
{ 
    ApplicationDataContainer roamingSettings = null; 

    private ObservableCollection<ComboBoxItem> ComboBoxOptions; 

    public MainPage() 
    { 
     this.InitializeComponent(); 
     ComboBoxOptions = new ObservableCollection<ComboBoxItem>(); 
     ComboBoxOptionsManager.GetComboBoxList(ComboBoxOptions); 


     roamingSettings = ApplicationData.Current.RoamingSettings; 


     var value = (string)roamingSettings.Values["ComboBoxSelection"]; 
     if (value != null) 
     { 
      SelectedComboBoxOption = Deserialize<ComboBoxItem>(value); //loaded selection reflected in the textbox but not in the ComboBox 
     } 
     else 
     { 
      SelectedComboBoxOption = ComboBoxOptions[0]; 
     } 

    } 

    public class ComboBoxItem 
    { 
     public string ComboBoxOption { get; set; } 
     public string ComboBoxHumanReadableOption { get; set; } 
    } 

    public class ComboBoxOptionsManager 
    { 
     public static void GetComboBoxList(ObservableCollection<ComboBoxItem> ComboBoxItems) 
     { 
      var allItems = getComboBoxItems(); 
      ComboBoxItems.Clear(); 
      allItems.ForEach(p => ComboBoxItems.Add(p)); 
     } 

     private static List<ComboBoxItem> getComboBoxItems() 
     { 
      var items = new List<ComboBoxItem>(); 

      items.Add(new ComboBoxItem() { ComboBoxOption = "Option1", ComboBoxHumanReadableOption = "Option 1" }); 
      items.Add(new ComboBoxItem() { ComboBoxOption = "Option2", ComboBoxHumanReadableOption = "Option 2" }); 
      items.Add(new ComboBoxItem() { ComboBoxOption = "Option3", ComboBoxHumanReadableOption = "Option 3" }); 

      return items; 
     } 
    } 

    private ComboBoxItem _SelectedComboBoxOption; 

    public ComboBoxItem SelectedComboBoxOption 
    { 
     get 
     { 
      return _SelectedComboBoxOption; 
     } 
     set 
     { 
      if (_SelectedComboBoxOption != value) 
      { 
       _SelectedComboBoxOption = value; 
       roamingSettings.Values["ComboBoxSelection"] = Serialize(value); 
       RaisePropertyChanged("SelectedComboBoxOption"); 
      } 
     } 
    } 




    public static string Serialize(object obj) 
    { 
     using (var sw = new StringWriter()) 
     { 
      var serializer = new XmlSerializer(obj.GetType()); 
      serializer.Serialize(sw, obj); 
      return sw.ToString(); 
     } 
    } 

    public static T Deserialize<T>(string xml) 
    { 
     using (var sw = new StringReader(xml)) 
     { 
      var serializer = new XmlSerializer(typeof(T)); 
      return (T)serializer.Deserialize(sw); 
     } 
    } 


    void RaisePropertyChanged(string prop) 
    { 
     if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
} 
} 

Antwort

6

ein typischer Fall von Artikel Dies, die gleich aussehen, sind aber nicht da Sie haben unterschiedliche Referenzen (lesen Sie C# reference types).

Sie laden die ComboBox mit 3 Werten und diese 3 Werte werden im Dropdown angezeigt. Um ein ausgewähltes Element zu sehen, wenn das ComboBox geschlossen ist, muss es (= dieselbe Referenz wie) einen dieser 3 Werte haben. Wenn Sie in Ihren Roaming-Einstellungen nichts gespeichert haben, wählen Sie das erste als SelectedItem. Wenn Sie zu einem anderen ausgewählten Objekt wechseln, haben Sie auch eine gültige Referenz in der SelectedItem-Eigenschaft.

Wenn Sie jedoch den gespeicherten Wert RoamingSettings deserialisieren, erstellen Sie ein neues Objekt mit einer anderen Referenz. Wenn Sie dieses Element als SelectedItem festlegen, wird das Steuerelement ComboBox es in seinen Elementen nicht finden und daher ein Element nicht auswählen.

Um dies zu beheben, müssen Sie das richtige Element in der ItemSource Sammlung finden müssen:

var value = (string)roamingSettings.Values["ComboBoxSelection"]; 
if (value != null) 
{ 
    var deserialized = Deserialize<ComboBoxItem>(value); 
    // using ComboBoxOption as the primary key field of your object 
    SelectedComboBoxOption = ComboBoxOptions.SingleOrDefault(c => 
       c.ComboBoxOption == deserialized.ComboBoxOption); 
} 
else 
{ 
    SelectedComboBoxOption = ComboBoxOptions[0]; 
}