1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WinUI3 ComboBoxを扱いたい!

Last updated at Posted at 2025-02-02

WinUI3のComboBoxについて学んだ事をアウトプットしていきたいと思います。

何か追加情報があれば都度記事を更新していこうと思います。

ComboBoxのパターン

今回は以下のパターンについて学びました。

  • 静的なアイテムの定義
  • 動的なアイテムの定義
  • 編集可能なアイテムの定義

まずはこれらのパターンを実装したコードサンプルを載せます。
その次のセクションで個々の詳細を記載していこうと思います。

MainWindow.xaml
<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Class="ComboBoxTest.MainWindow"
    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"
    Title="ComboBoxTest">

    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" Margin="30">
        <TextBlock Text="{x:Bind TextViewModel.Name, Mode=OneWay}" 
                   Foreground="{x:Bind TextViewModel.Color, Mode=OneWay}"
                   FontSize="{x:Bind TextViewModel.Size, Mode=OneWay}"
                   Margin="10" />
        <ComboBox Header="色" PlaceholderText="色を選択してください" 
                  SelectionChanged="ComboBox_SelectionChanged_Color"
                  Width="200"
                  Margin="5">
            <x:String>Red</x:String>
            <x:String>Green</x:String>
            <x:String>Blue</x:String>
        </ComboBox>
        <ComboBox Header="名前" PlaceholderText="名前を選択してください" 
                  SelectionChanged="ComboBox_SelectionChanged_Name"
                  ItemsSource="{x:Bind TextViewModel.Names}"
                  SelectedItem="{x:Bind SelectedName, Mode=TwoWay}"
                  Width="200"
                  Margin="5" />
        <!-- サイズは直接入力が可能です。 -->
        <ComboBox Header="サイズ" PlaceholderText="サイズを選択してください"
                  SelectionChanged="ComboBox_SelectionChanged_Size"
                  ItemsSource="{x:Bind TextViewModel.Sizes}"
                  SelectedIndex="5"
                  IsEditable="True"
                  Width="200"
                  Margin="5" />
    </StackPanel>
</Window>
MainWindow.xaml.cs
public sealed partial class MainWindow : Window
{
    private TextViewModel TextViewModel { get; }
    private string SelectedName { get; set; } = string.Empty;

    public MainWindow()
    {
        this.InitializeComponent();

        // ウィンドウのサイズを変更します。
        // SizeInt32(Width, Height)
        SizeInt32 size = new(300, 500);
        AppWindow.Resize(size);

        TextViewModel = new();
    }

    // 色一覧を選択した場合の処理です。
    private void ComboBox_SelectionChanged_Color(object sender, SelectionChangedEventArgs e)
    {
        // コンボボックスから選択した項目を取得します。
        string colorName = e.AddedItems[0].ToString() ?? string.Empty;
        TextViewModel.Color = colorName;
    }

    // 名前一覧を選択した場合の処理です。
    private void ComboBox_SelectionChanged_Name(object sender, SelectionChangedEventArgs e)
    {
        // コンボボックスから選択した項目を取得します。
        TextViewModel.Name = SelectedName;
    }

    // サイズ一覧を選択した場合の処理です。
    private void ComboBox_SelectionChanged_Size(object sender, SelectionChangedEventArgs e)
    {
        // コンボボックスから選択した項目を取得します。
        string size = e.AddedItems[0].ToString() ?? string.Empty;
        TextViewModel.Size = uint.Parse(size);
    }
}
TextViewModel.cs
internal class TextViewModel : INotifyPropertyChanged
{
    private TextModel _model = new();

    // コンボボックスに表示する名前一覧です。
    public string[] Names
    {
        get
        {
            return _model.Names;
        }
    }

    // テキストに表示する名前です。
    public string Name
    {
        get
        {
            return $"あなたの名前は{_model.Name}です。";
        }
        set
        {
            _model.Name = value;
            OnPropertyChanged();
        }
    }

    // テキストの色です。
    public string Color
    {
        get
        {
            return _model.Color;
        }
        set
        {
            _model.Color = value;
            OnPropertyChanged();
        }
    }

    // コンボボックスに表示するサイズ一覧です。
    public uint[] Sizes
    {
        get
        {
            return _model.Sizes;
        }
    }

    // テキストのサイズです。
    public uint Size
    {
        get
        {
            return _model.Size;
        }
        set
        {
            _model.Size = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler? PropertyChanged = delegate { };
    protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
TextModel.cs
internal class TextModel
{
    // コンボボックスに表示する名前の一覧です。
    public string[] Names { get; } =
    {
        "紫咲シオン",
        "宝鐘マリン",
        "雪花ラミィ",
        "戌神ころね",
        "大神ミオ",
        "さくらみこ",
        "姫森ルーナ",
        "博衣こより",
        "猫又おかゆ",
        "桃鈴ねね",
        "白上フブキ",
        "常闇トワ",
        "兎田ぺこら",
        "白銀ノエル",
        "ラプラス・ダークネス"
    };

    // コンボボックスに表示するサイズの一覧です。
    public uint[] Sizes { get; } =
    {
        8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 36, 48, 72,
    };

    // テキストに表示する名前です。
    public string Name { get; set; } = "*******";
    // テキストの色です。
    public string Color { get; set; } = "Black";
    // テキストのサイズです。
    public uint Size = 11;
}

2025.02.03-1.jpg

静的なアイテムの定義パターン

ComboBoxの子要素としてx:stringをアイテムの数だけ定義します。
今回のサンプルでは色の定義として使用しています。

MainWindow.xaml
<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Class="ComboBoxTest.MainWindow"
    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"
    Title="ComboBoxTest">

    <!-- 省略 -->
      
        <ComboBox Header="色" PlaceholderText="色を選択してください" 
                  SelectionChanged="ComboBox_SelectionChanged_Color"
                  Width="200"
                  Margin="5">
            <x:String>Red</x:String>
            <x:String>Green</x:String>
            <x:String>Blue</x:String>
        </ComboBox>

    <!-- 省略 -->
</Window>

アイテムを選択するとSelectionChangedイベントが呼び出されます。
これの実装として、e.AddedItems[]の0番目の文字列表現を取得することで選択したアイテムを取得、設定します。

MainWindow.xaml.cs
public sealed partial class MainWindow : Window
{
    // 省略

    private void ComboBox_SelectionChanged_Color(object sender, SelectionChangedEventArgs e)
    {
        // コンボボックスから選択した項目を取得します。
        string colorName = e.AddedItems[0].ToString() ?? string.Empty;
        TextViewModel.Color = colorName;
    }

    // 省略
}

2025.02.03-4.jpg

動的なアイテムの定義パターン

動的なアイテムにはItemSource属性にコレクションを設定します。

MainWindow.xaml
<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Class="ComboBoxTest.MainWindow"
    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"
    Title="ComboBoxTest">
      <!-- 省略 -->
      
        <ComboBox Header="名前" PlaceholderText="名前を選択してください" 
                  SelectionChanged="ComboBox_SelectionChanged_Name"
                  ItemsSource="{x:Bind TextViewModel.Names}"
                  SelectedItem="{x:Bind SelectedName, Mode=TwoWay}"
                  Width="200"
                  Margin="5" />

        <!-- 省略 -->
</Window>

また、ここでは選択されたアイテムの取得方法にSelectedItem属性を設定することで実装しています。
この属性はコードビハインド側と双方向になるため、ModeにはTwoWayを指定しています。

MainWIndow.xaml.cs
public sealed partial class MainWindow : Window
{
    private TextViewModel TextViewModel { get; }
    private string SelectedName { get; set; } = string.Empty;

    public MainWindow()
    {
         // 省略
    }

      // 省略

    private void ComboBox_SelectionChanged_Name(object sender, SelectionChangedEventArgs e)
    {
        // コンボボックスから選択した項目を取得します。
        TextViewModel.Name = SelectedName;
    }

      // 省略
}

ComboBoxに定義するアイテムはモデル側で定義した値を使用しています。
今回は名前一覧を作成するため、string型の配列を定義します

TextModel.cs
internal class TextModel
{
    // コンボボックスに表示する名前の一覧です。
    public string[] Names { get; } =
    {
        "紫咲シオン",
        "宝鐘マリン",
        "雪花ラミィ",
        "戌神ころね",
        "大神ミオ",
        "さくらみこ",
        "姫森ルーナ",
        "博衣こより",
        "猫又おかゆ",
        "桃鈴ねね",
        "白上フブキ",
        "常闇トワ",
        "兎田ぺこら",
        "白銀ノエル",
        "ラプラス・ダークネス"
    };

    // 省略
}

また、ここでは大量のアイテムを定義していますが、表示されるアイテムの量が多い場合、一定の数からスクロールバーが表示されるようになります。

2025.02.03-2.jpg

編集可能なアイテムの定義パターン

IsEditable属性をTrueにすることでComboBox内の値を直接編集することが可能です。

MainWindow.xaml
<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Class="ComboBoxTest.MainWindow"
    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"
    Title="ComboBoxTest">
      <!-- 省略 -->
      
       <ComboBox Header="サイズ" PlaceholderText="サイズを選択してください"
                 SelectionChanged="ComboBox_SelectionChanged_Size"
                 ItemsSource="{x:Bind TextViewModel.Sizes}"
                 SelectedIndex="5"
                 IsEditable="True"
                 Width="200"
                 Margin="5" />

        <!-- 省略 -->
</Window>

またSelectedIndex属性に値を設定することでこの位置を選択した状態にすることが可能です。

2025.02.03-3.jpg

おわりに

ComboBoxにはまだ定義できる属性があります。
ただ現段階で私が使いそうだな、と思ったのが今回載せたパターンです。

今後これも使いそうとなりましたら都度更新していこうと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?