WPFのコンボボックスでサジェッションのようなことをする

C# コンピュータ
C#

入力候補としてサジェッションを表示する方法を探していますが、コンボボックスで作ってみました。

ファイル名:MainWindow.xaml

<Window
  x:Class="ComboboxSample01.MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:local="clr-namespace:ComboboxSample01"
  mc:Ignorable="d"
  Height="450"
  Width="800"
  Title="{Binding Title.Value}"
  xmlns:interactivity="clr-namespace:Reactive.Bindings.Interactivity;assembly=ReactiveProperty.WPF"
  xmlns:i="clr-namespace:Microsoft.Xaml.Behaviors;assembly=Microsoft.Xaml.Behaviors">
  <Window.DataContext>
    <local:MainWindowViewModel />
  </Window.DataContext>
  <Grid>
        <StackPanel>
          <ComboBox IsEditable="True"
                ItemsSource="{Binding Suggestions}"
                SelectedItem="{Binding SelectedSuggestion.Value}"
                Text="{Binding InputText.Value}">
            </ComboBox>
          <Button Content="追加"
            Command="{Binding AddSuggestionsCommand}" 
            IsEnabled="{Binding AddSuggestionsEnable.Value}"/>
        </StackPanel>
  </Grid>
</Window>

ファイル名:MainWindowViewModel

using System.Diagnostics;
using System.ComponentModel;
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using System.Reactive.Disposables;
using System.Windows;

namespace ComboboxSample01;
public class MainWindowViewModel : INotifyPropertyChanged
{
    // INotifyPropertyChanged
    public event PropertyChangedEventHandler? PropertyChanged;
    protected virtual void OnPropertyChanged(string name) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    // IDisposable

    /**************************************************************************
    * プロパティ
    **************************************************************************/
    public ReactiveProperty<string> Title { get; private set; }
         = new ReactiveProperty<string>("Title");
    // サジェッション
    public ReactiveCollection<string> Suggestions { get; private set; } = [];
    // 選択した値
    public ReactiveProperty<string> SelectedSuggestion { get; private set; }
         = new ReactiveProperty<string>("");
    // 入力値
    public ReactiveProperty<string> InputText { get; private set; }
         = new ReactiveProperty<string>("");
    // 追加ボタン
    public ReactiveCommand<System.Windows.Input.KeyEventArgs> AddSuggestionsCommand { get; } = new();
    // 追加ボタンの有効無効
    public ReactiveProperty<bool> AddSuggestionsEnable {get; private set;} = new(false);
    public MainWindowViewModel()
    {
        PropertyChanged += (s, e) => {};

        // サジェスチョンの初期化
        var items = new string[]{"Apple", "Orange", "Banana"};
        foreach (var item in items) {
            Suggestions.AddOnScheduler(item);
        }
        // サジェスチョン変化
        SelectedSuggestion.Subscribe(e=>{
            Debug.Print($"select:{SelectedSuggestion.Value}");
        });
        // 入力値
        InputText.Subscribe(e=>{
            Debug.Print($"input:{InputText.Value}");
            if ("" == InputText.Value) return;
            AddSuggestionsEnable.Value = (Suggestions.IndexOf(InputText.Value) < 0);
        });
        // 追加ボタンを押した
        AddSuggestionsCommand.Subscribe(e=>{
            string item = InputText.Value;

            var result = MessageBox.Show(
                $"「{item}」を追加しますか?",
                "確認", MessageBoxButton.YesNo, MessageBoxImage.Question);
            if (MessageBoxResult.Yes != result) return;


            Debug.Print(item);
            // コレクションに追加
            Suggestions.AddOnScheduler(item);
            // 選択
            SelectedSuggestion.Value = item;
        });
    }
}

コンボボックスのIsEditabletureにすると編集可能になります。

そちらに追加したい文字を入力し「追加」ボタンを押すと

コンボボックスの選択肢に追加されます。

コメント