UWP ComboBox(プルダウンメニュー)の使い方まとめ

操作に手こずったのでメモ。  

  

ComboBoxとは?

これ。

f:id:Tiratom:20190427205449p:plain

色々前提

・画面の見た目の制御を行なっているXAMLのファイル名を「MainPage.xaml」とします。  
・MainPage.xaml.cs内では、 

public sealed partial class MainPage : Page {
    public ViewModels.MainPageViewModel ViewModel { get; private set: } = new ViewModels.MainPageViewModel();
    // 他のコードは省略  
}  

のように、MainPageViewModelクラスのViewModelという変数を宣言しています。なので、XAML内で「ViewModel.xxxx 」というのが出てきたときはこのMainPageViewModelクラスの中の変数だなと思ってください。

設定値・設定内容について

まず、XAML(MainPage.xaml)はこうなっています。 (設定内容はあくまで一例としてとらえてください)

<ComboBox
    x:Name="HogeCombo"
    Width="470"
    Margin="5,5,5,5"
    HorizontalAlignment="Stretch"
    VerticalAlignment="Top"
    DisplayMemberPath="Content"
    Header="{x:Bind ViewModel.HeaderText, Mode=OneWay}"
    ItemsSource="{x:Bind ViewModel.ComboItemSource, Mode=OneWay}"
    PlaceholderText="{x:Bind ViewModel.PlaceHolderText}"
    SelectedItem="{x:Bind ViewModel.SelectedItemData, Mode=TwoWay}"
    SelectedValue="{x:Bind ViewModel.SelectedValueData, Mode=TwoWay}"
    SelectedValuePath="Id" />

細かく見ていきたいと思います。

x:Name : 名前ですね。僕はとりあえず書いていましたが使っていないです。

Width : ComboBoxの幅です。

Margin : ComboBoxのマージンです。マージンの説明は割愛します。  

HorizontalAlignment : ComboBoxの水平方向の位置・長さ調節です。僕の設定値は「Stretch」なので、1つ上の階層の構造に合わせて横いっぱいに広がります。

VerticalAlignment : ComboBoxの縦方向の位置・長さ調節です。僕の設定値は「Top」なので、1つ上の階層の構造に合わせて上寄せで表示されます。

DislayMemberPath : ComboBoxの選択肢として表示するプロパティ名です。記事の最初に乗せたキャプチャでいう「Menu3」に該当するプロパティに関する設定です。詳しくは後述します。

Header : ComboBoxのヘッダー部分(四角の枠の上部分)に表示する文言を設定します。バインドしている値は、ただの文字列です。
この記事の先頭付近に張り付けた画像には、ヘッダーは入っていないので注意して下さい。

ItemSource : ComboBoxに持たせる各選択肢についての情報を持つマスター的なデータです。詳しくは後述します。
 
PlaceholderText : 何も選択していないときに表示する内容です。バインドしている値はただの文字列です。

SelectedItem : ComboBoxで選択されたアイテムを表します。詳しくは後述します。

SelectedValue : ComboBoxで選択された値を表します。選択されたデータの、SelectedValuePathで指定したプロパティの値が対応します。詳しくは後述します。

SelectedValuePath : ComboBoxで選択されたときの値とするプロパティを設定します。詳しくは後述します。

いろいろ詳細

ItemSource(ComboBoxの選択肢一覧)について。

XAML上でのバインド値:
ItemsSource="{x:Bind ViewModel.ComboItemSource, Mode=OneWay}"

ViewModelのComboItemSourceプロパティの値をリストの選択肢一覧として出してね、という設定をしています。

   

MainPageViewModelクラス(ViewModel)で設定している内容
public ObservableCollection<ComboBoxItem> ComboItemSource{ get; set; } = new ObservableCollection<ComboBoxItem>();

「ObservableCollectionクラスは、項目が追加または削除された場合に、通知を提供するコレクションクラス」(https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/data/how-to-create-and-bind-to-an-observablecollection)です。
ComboItemSourceの変更は見た目にすぐ反映させたかったのでこのクラスを用いています。

※ 僕が勝手に作ったクラスですが、ComboBoxItemクラスの定義 は以下のようにしています。

public class ComboBoxItem{
     string Id {get; set;}
     string Content {get; set;}
}

 

MainPageViewModelクラス(ViewModel)でのComboBoxItemListの設定例

僕のソース内ではこのようにComboBoxItemListを設定しています。

// 僕のソースでは別の値を入れていることがありうるので、一旦リセットしてから値を入れ直す  
ComboBoxItemList.Clear();

// 説明用にダミーのリストを用意  
List<ComboBoxItem> dummyList = new List<ComboBoxItem>(){
    { "1", "menu1"},
    { "2", "menu2"},
    { "3", "menu3"},
};

// 説明用のダミーのリストの各データを、ComboBoxItemListに追加  
dummyList.ForEach(i=>
{
    ComboBoxItem item= new ComboBoxItem
    {
        Id= i.Id,
        Content = i.Content
    };
    ComboBoxItemList.Add(item);
});

このようにしておけば、コンボボックスの選択肢一覧を用意することができます。
 
 

DisplayMemberPathの値

ComboBoxの選択肢に表示する内容のプロパティ名です。
僕の設定値は「Content」になっています。これは、先ほど説明したItemSourceで設定したコレクションクラスの中のContentプロパティを表示して下さい、ということになります。
 
ItemSourceの設定内容は

ItemsSource="{x:Bind ViewModel.ComboItemSource, Mode=OneWay}"

で、具体的な中身としては

public ObservableCollection<ComboBoxItem> ComboItemSource{ get; set; } = new ObservableCollection<ComboBoxItem>();

を設定していて、
僕作成のComboBoxItemの定義は

public class ComboBoxItem{
     string Id {get; set;}
     string Content {get; set;}
}

となっていて、このContentには「Menu3」等の値が設定されているので、
f:id:Tiratom:20190427205449p:plain
という見た目になるということです。
 

SelectedItemの値

これは、コンボボックスで選択されているデータの値を格納しておく変数を指定します。
 

XAML上でのバインド値:
SelectedItem="{x:Bind ViewModel.SelectedItemData, Mode=TwoWay}"

僕の場合、XAMLではこのように設定しているので、 ViewModelインスタンスのSelectedItemDataという変数に選択されたデータについての情報が格納されます。

 

MainPageViewModelクラス(ViewModel)で設定している内容
private ComboBoxItem SelectedItemData;

このように、MainPageViewModelクラス(ViewModel)内では先ほど出てきたComboBoxItemクラスの変数を用意しています。
なので、ソース内でSelectedItemData.Id や SelectedItemData.Contentとすれば選択されたデータの中身が取得できます。

  

  

SelectedValue, SelectedValuePathの値

コンボボックスで選択されているデータの特定の値を格納しておく変数を指定します。
SelectedItemとの違いについて説明します。

XAML上では以下のように設定しました。(一部抜粋)

ItemsSource="{x:Bind ViewModel.ComboItemSource, Mode=OneWay}"
SelectedValue="{x:Bind ViewModel.SelectedValueData, Mode=TwoWay}"  
SelectedValuePath="Id"

これにより、SelecteValueには、ComboItemSource(=ItemsSourceで設定されている値)のコレクションの中の1アイテムに該当するクラスのIdプロパティ(=SelectedValuePathの設定値)が設定されます。

場当たり的な使い方で申し訳ないのですが、コンボボックスにあらかじめある選択肢を選択させておく、という実装を行ったときに、SelectedItemへの値設定だけではうまく設定することがうまくできなかったため、SelectedItemとSelectedValueを両方用意しています。 (その部分の実装については割愛)

 

 
 

ずっと下書きに書きかけておいたやつをやっと公開しました・・すぐ書いてすぐ公開しないと内容があやふやになりますね・・・。