2015-11-22 19 views
5

Questa è una continuazione da an earlier question.UWP riflette l'elemento selezionato CombBox caricato dalle impostazioni tramite associazione

Per alcune impostazioni dell'app, desidero utilizzare un ComboBox per selezionare un'opzione. Posso salvare l'opzione selezionata su (roaming) e caricarla di nuovo. L'opzione caricata viene visualizzata correttamente in TextBlock ma il ComboBox mostra uno spazio vuoto. Come posso riflettere anche l'opzione attualmente selezionata caricata nel ComboBox?

Questa è la 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> 

e questo è il codice dietro:

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

risposta

6

questo un tipico caso di articoli che hanno lo stesso aspetto, ma non sono in quanto hanno riferimenti diversi (leggi su C# reference types).

Si carica il ComboBox con 3 valori e questi 3 valori sono visualizzati nel menu a discesa. Per vedere un oggetto selezionato quando lo ComboBox è chiuso, deve essere (= avere lo stesso riferimento di) uno di questi 3 valori. Quando non hai salvato nulla nelle impostazioni di roaming, seleziona il primo come SelectedItem. Passando a un altro elemento selezionato, si avrà anche un riferimento valido nella proprietà SelectedItem.

Tuttavia, quando si deserializza il valore salvato RoamingSettings, si crea un nuovo oggetto con un riferimento diverso. Quando si imposta questo articolo come SelectedItem, il controllo ComboBox non lo troverà nei suoi elementi e quindi non selezionerà un elemento.

Per risolvere questo problema, si dovrà trovare l'articolo corretto nella raccolta ItemSource:

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]; 
} 
Problemi correlati