2015-11-22 15 views
5

Jest to kontynuacja z an earlier question.UWP odzwierciedlają wybrany element CombBox załadowany z ustawień poprzez powiązanie

Dla niektórych ustawień aplikacji chcę użyć ComboBox do wybrania opcji. Mogę zapisać wybrane ustawienia do (roaming) i załadować je ponownie. Załadowana opcja jest poprawnie wyświetlana w TextBlock, ale ComboBox pokazuje puste pole. Jak mogę również odzwierciedlić załadowaną aktualnie wybraną opcję w ComboBox?

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

I to jest kod za:

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

Odpowiedz

6

To typowy przypadek elementów, które wyglądają tak samo, ale nie są od mają różne odniesienia (przeczytaj na C# reference types).

Załadujesz ComboBox z 3 wartościami i te 3 wartości są pokazane na liście rozwijanej. Aby zobaczyć wybrany element, gdy ComboBox jest zamknięty, musi mieć (= mieć takie samo odniesienie jak) jedną z tych 3 wartości. Jeśli nie masz nic zapisanego w ustawieniach roamingu, wybierz pierwszy jako SelectedItem. Przechodząc do innego wybranego elementu, będziesz mieć również prawidłowe odniesienie we właściwości SelectedItem.

Jednak po deserializacji zapisanej wartości RoamingSettings utworzysz nowy obiekt z innym odniesieniem. Po ustawieniu tego elementu jako SelectedItem, element sterujący nie znajdzie go w swoich elementach, a zatem nie wybierze elementu.

Aby rozwiązać ten problem, trzeba znaleźć właściwą pozycję w kolekcji 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]; 
} 
Powiązane problemy