--- lang: ja-jp breaks: true --- # `WinUI 3` 複数選択可能なコンボボックスの実装 2022-12-03 :::warning ※一部、無理やり実装しています。 ::: ## 参考 > WPF ComboBoxのドロップダウンの表記と選択部の表記を変更したい > https://teratail.com/questions/246077 > Using a different DataTemple when a WPF ComboBox is expanded > https://www.codeproject.com/Articles/47923/Using-a-different-DataTemple-when-a-WPF-ComboBox-i ## 画面 ![](https://i.imgur.com/krOFObB.png) ![](https://i.imgur.com/PxtuzIs.png) ## csproj ```xml= ・・・ <ItemGroup> <PackageReference Include="CommunityToolkit.Mvvm" Version="7.1.2" /> </ItemGroup> ・・・ ``` ## MainWindow.xaml ```xml= <!-- Copyright (c) Microsoft Corporation and Contributors. --> <!-- Licensed under the MIT License. --> <Window x:Class="MultiSelectCombobox.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:MultiSelectCombobox" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> <ComboBox ItemsSource="{x:Bind ViewModel.FinancialStatusViewRows, Mode=TwoWay}" SelectedItem="{x:Bind ViewModel.SelectedFinancialStatusItem, Mode=TwoWay}" DropDownClosed="ComboBox_DropDownClosed" > <ComboBox.Resources> <DataTemplate x:Key="comboboxItemTemplate"> <StackPanel Orientation="Horizontal"> <CheckBox IsChecked="{Binding Checked, Mode=TwoWay}" Content="{Binding Text}" VerticalAlignment="Center" /> </StackPanel> </DataTemplate> <DataTemplate x:Key="comboboxSelectedContentTemplate"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding SelectedText, Mode=OneWay}" VerticalAlignment="Center" /> </StackPanel> </DataTemplate> </ComboBox.Resources> <ComboBox.ItemTemplateSelector> <local:MultiSelectDataTemplateSelector DataTemplate_Items="{StaticResource comboboxItemTemplate}" DataTemplate_SelectedContent="{StaticResource comboboxSelectedContentTemplate}" /> </ComboBox.ItemTemplateSelector> </ComboBox> </StackPanel> </Window> ``` ## MainWindow.xaml.cs ```csharp= public sealed partial class MainWindow : Window { public MainWindow() { ViewModel = new(); this.InitializeComponent(); } public MainWindowViewModel ViewModel { get; } private void ComboBox_DropDownClosed(object sender, object e) { ViewModel.DropDownClosed_FinancialStatus.Execute(e); } } ``` ## MainWindowViewModel.cs ```csharp= public sealed class MainWindowViewModel : ObservableRecipient { public MainWindowViewModel() : base() { DropDownClosed_FinancialStatus = new RelayCommand(DropDownClosed_FinancialStatusCommand); { m_lstFinancialStatusViewRows = new(); m_lstFinancialStatusViewRows.Add(new MultiSelectComboboxRowData(false, "与信済み", "authorized", "")); m_lstFinancialStatusViewRows.Add(new MultiSelectComboboxRowData(false, "与信停止", "pending", "")); m_lstFinancialStatusViewRows.Add(new MultiSelectComboboxRowData(true, "支払済み", "paid", "")); m_lstFinancialStatusViewRows.Add(new MultiSelectComboboxRowData(false, "一部支払済み", "partially_paid", "")); m_lstFinancialStatusViewRows.Add(new MultiSelectComboboxRowData(false, "返金済み", "refunded", "")); m_lstFinancialStatusViewRows.Add(new MultiSelectComboboxRowData(false, "支払無効", "voided", "")); m_lstFinancialStatusViewRows.Add(new MultiSelectComboboxRowData(false, "一部返金済み", "partially_refunded", "")); m_lstFinancialStatusViewRows.Add(new MultiSelectComboboxRowData(false, "未払い", "unpaid", "")); m_lstFinancialStatusViewRows.Add(new MultiSelectComboboxRowData(false, "全て", "any", "")); string selectedFinancialStatusViewRows = string.Join( ", ", m_lstFinancialStatusViewRows .Where(n => n.Checked) .Select(n => n.Text) ); foreach (MultiSelectComboboxRowData row in m_lstFinancialStatusViewRows) { row.SelectedText = selectedFinancialStatusViewRows; } m_selectedFinancialStatusItem = m_lstFinancialStatusViewRows.First(); } } ObservableCollection<MultiSelectComboboxRowData> m_lstFinancialStatusViewRows; public ObservableCollection<MultiSelectComboboxRowData> FinancialStatusViewRows { get => m_lstFinancialStatusViewRows; set => SetProperty(ref m_lstFinancialStatusViewRows, value); } private MultiSelectComboboxRowData m_selectedFinancialStatusItem; public MultiSelectComboboxRowData SelectedFinancialStatusItem { get => m_selectedFinancialStatusItem; set => SetProperty(ref m_selectedFinancialStatusItem, value); } public ICommand DropDownClosed_FinancialStatus { get; } private void DropDownClosed_FinancialStatusCommand() { string selectedFinancialStatusViewRows = string.Join( ", ", FinancialStatusViewRows .Where(n => n.Checked) .Select(n => n.Text) ); foreach (MultiSelectComboboxRowData row in FinancialStatusViewRows) { row.SelectedText = selectedFinancialStatusViewRows; } } } ``` ## MultiSelectDataTemplateSelector.cs ```csharp= public sealed class MultiSelectDataTemplateSelector: DataTemplateSelector { protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { if (item is MultiSelectComboboxRowData comboboxRowData) { ; } if (container is ComboBoxItem comboBoxItem) { return m_dataTemplate_Items; } else if (container is ContentPresenter contentPresenter) { return m_dataTemplate_SelectedContent; } return base.SelectTemplateCore(item, container); } private DataTemplate m_dataTemplate_Items; private DataTemplate m_dataTemplate_SelectedContent; public DataTemplate DataTemplate_Items { get { return this.m_dataTemplate_Items; } set { this.m_dataTemplate_Items = value; } } public DataTemplate DataTemplate_SelectedContent { get { return this.m_dataTemplate_SelectedContent; } set { this.m_dataTemplate_SelectedContent = value; } } } ``` ## MultiSelectComboboxRowData.cs ```csharp= public sealed class MultiSelectComboboxRowData { private bool m_checked; private string m_text; private string m_code; private string m_selectedText; /// <summary> /// /// </summary> /// <param name="checked "></param> /// <param name="text "></param> /// <param name="code "></param> /// <param name="selectedText "></param> public MultiSelectComboboxRowData( bool @checked, string text, string code, string selectedText ) : base() { this.m_checked = @checked; this.m_text = text; this.m_code = code; this.m_selectedText = selectedText; } /// <summary> /// /// </summary> /// <param name="org"></param> public MultiSelectComboboxRowData( MultiSelectComboboxRowData org ) : base() { this.m_checked = org.m_checked; this.m_text = org.m_text; this.m_code = org.m_code; this.m_selectedText = org.m_selectedText; } public bool Checked { get { return this.m_checked; } set { this.m_checked = value; } } public string Text { get { return this.m_text; } set { this.m_text = value; } } public string Code { get { return this.m_code; } set { this.m_code = value; } } public string SelectedText { get { return this.m_selectedText; } set { this.m_selectedText = value; } } public override string ToString() { return new StringBuilder() .Append("checked:").Append(m_checked).AppendLine("、") .Append("text:").Append(m_text).AppendLine("、") .Append("code:").Append(m_code).AppendLine("、") .Append("selectedText:").Append(m_selectedText).AppendLine() .ToString(); } } ``` ###### tags: `WinUI 3` `Combobox` `Checkbox` `複数選択コンボボックス`