2015-11-22 8 views
5

これはan earlier questionの続きです。UWPはバインドによって設定からロードされたCombBox選択項目を反映します

一部のアプリの設定では、ComboBoxを使用してオプションを選択したいと考えています。選択したオプションを(ローミング)設定に保存して、もう一度ロードすることができます。ロードされたオプションはTextBlockに正しく​​表示されますが、ComboBoxには空白が表示されます。現在選択されているロードされたオプションをコンボボックスに反映させるにはどうしたらいいですか?

この

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

そして、これは背後にあるコードです:

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

答えて

6

これと同じように見えますが、以降でない項目の典型的なケース彼らは異なった参照を持っています(C# reference typesで読む)。

ComboBoxを3つの値で読み込み、これらの3つの値がドロップダウンボックスに表示されます。 ComboBoxが閉じているときに選択したアイテムを表示するには、これらの3つの値のいずれかと同じ参照を持つ必要があります。ローミング設定で何も保存されていない場合は、最初の設定をSelectedItemとして選択します。選択した別のアイテムに切り替えると、SelectedItemプロパティにも有効な参照が表示されます。

ただし、保存されたRoamingSettingsの値を逆シリアル化すると、別の参照で新しいオブジェクトが作成されます。このアイテムをSelectedItemと設定すると、ComboBoxコントロールはアイテム内でそのアイテムを検出せず、アイテムを選択しません。

これを修正するには、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]; 
} 
関連する問題