最終的にいくつかの設定に使用できるように、バインディングでコンボボックスを機能させようとしています。監視可能なコレクションから入力するアイテムを取得し、「SelectedItem」をプロパティにバインドできますSelectedItem="{x:Bind SelectedComboBoxOption}"
しかし、選択を変更すると、テキストボックスには反映されず、このプロパティにもバインドされます。背後のコードでは、起動時にプロパティを1回設定しますが、コンボボックスのアイテムを変更するときは設定しません。私は何かを逃しているに違いありませんが、私には何が明確ではありません。何か案は?
これは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"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<ComboBox
Name="ComboBox"
ItemsSource="{x:Bind ComboBoxOptions}"
SelectedItem="{x:Bind SelectedComboBoxOption, Mode=TwoWay}"
SelectedValuePath="ComboBoxOption"
DisplayMemberPath="ComboBoxHumanReadableOption"
Header="ComboBox" >
</ComboBox>
<TextBlock Name="BoundTextblock" Text="{x:Bind SelectedComboBoxOption}"/>
</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 Windows.Foundation;
using Windows.Foundation.Collections;
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;
namespace ComboBoxTest
{
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
private ObservableCollection<ComboBoxItem> ComboBoxOptions;
public MainPage()
{
this.InitializeComponent();
ComboBoxOptions = new ObservableCollection<ComboBoxItem>();
ComboBoxOptionsManager.GetComboBoxList(ComboBoxOptions);
}
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;
}
}
string _SelectedComboBoxOption = "Option1";
public string SelectedComboBoxOption
{
get
{
return _SelectedComboBoxOption;
}
set
{
if (_SelectedComboBoxOption != value)
{
_SelectedComboBoxOption = value;
RaisePropertyChanged("SelectedComboBoxOption");
}
}
}
void RaisePropertyChanged(string prop)
{
if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); }
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
@Mike Easonと@kubakistaが言ったように、Mode
を明示的に設定する必要があります。ただし、これで問題が完全に修正されるわけではありません。
コードでは、SelectedComboBoxOption
は文字列ですが、SelectedItem
はComboBoxItem
オブジェクトです。 String
をSelectedItem
にバインドしても、ComboBox
の選択されたアイテムは変更されません。したがって、SelectedComboBoxOption
を使用してComboBox
の選択した項目を取得および設定する場合は、SelectedComboBoxOption
をComboBoxItem
に変更し、{x:Bind}
で変換を使用してObject
とComboBoxItem
を変換する必要があります。
変換は次のようになります:
public class ComboBoxItemConvert : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value as MainPage.ComboBoxItem;
}
}
XAMLは次のようになります:
<Page ...>
<Page.Resources>
<local:ComboBoxItemConvert x:Key="ComboBoxItemConvert" />
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<ComboBox Name="ComboBox"
DisplayMemberPath="ComboBoxHumanReadableOption"
Header="ComboBox"
ItemsSource="{x:Bind ComboBoxOptions}"
SelectedItem="{x:Bind SelectedComboBoxOption, Mode=TwoWay, Converter={StaticResource ComboBoxItemConvert}}"
SelectedValuePath="ComboBoxOption" />
<TextBlock Name="BoundTextblock" Text="{x:Bind SelectedComboBoxOption.ComboBoxHumanReadableOption, Mode=OneWay}" />
</StackPanel>
</Grid>
</Page>
分離コード内:
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
private ObservableCollection<ComboBoxItem> ComboBoxOptions;
public MainPage()
{
this.InitializeComponent();
ComboBoxOptions = new ObservableCollection<ComboBoxItem>();
ComboBoxOptionsManager.GetComboBoxList(ComboBoxOptions);
SelectedComboBoxOption = ComboBoxOptions[0];
}
...
private ComboBoxItem _SelectedComboBoxOption;
public ComboBoxItem SelectedComboBoxOption
{
get
{
return _SelectedComboBoxOption;
}
set
{
if (_SelectedComboBoxOption != value)
{
_SelectedComboBoxOption = value;
RaisePropertyChanged("SelectedComboBoxOption");
}
}
}
...
}
選択したアイテムをTextBlock
に表示するだけの場合は、簡単な方法があります。 TextBlock
のText
プロパティをComboBox
のSelectedItem
にバインドできます。また、SelectedItem
の型はSystem.Object
であり、{x:Bind}
は厳密に型指定されており、パス内の各ステップの型を解決することに注意してください。返された型にメンバーがない場合、コンパイル時に失敗します。したがって、オブジェクトの実際のタイプをバインドするように指示するキャストを指定する必要があります。しかし、ネストされたクラスを{x:Bind}
にキャストするときに issue があります。回避策として、ComboBoxItem
をMainPage
から除外できます。
namespace ComboBoxTest
{
public class ComboBoxItem
{
public string ComboBoxOption { get; set; }
public string ComboBoxHumanReadableOption { get; set; }
}
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
...
}
}
そしてXAMLでは:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<ComboBox Name="ComboBox"
DisplayMemberPath="ComboBoxHumanReadableOption"
Header="ComboBox"
ItemsSource="{x:Bind ComboBoxOptions}"
SelectedValuePath="ComboBoxOption" />
<TextBlock Name="BoundTextblock" Text="{x:Bind ComboBox.SelectedItem.(local:ComboBoxItem.ComboBoxHumanReadableOption), Mode=OneWay}" />
</StackPanel>
</Grid>
デフォルトでは、x:Bind
はOneTime
に設定されます。モードをOneWay
に設定するだけでこれを修正できます。
Text="{x:Bind SelectedComboBoxOption, Mode=OneWay}"
別の解決策(もう少しMVVMのようなもの)は、コードビハインドでComboBoxItem型のオブジェクトを作成し、そのオブジェクトにバインドしてから、コードビハインドでオブジェクトを操作して目的の文字列を取得することです。これにより、コンバータを作成する必要がなくなります。
C#
public ComboBoxItem ComboBoxItemSelected {get; set;}
XAML
SelectedItem = "{Binding ComboBoxItemSelected, Mode=TwoWay}"