C#のListBoxを使ってみた

C#のWPFで、ListBoxにアイテムの追加と削除をしてみました。

目次

  1. ListBoxに表示されるアイテムの追加と削除
    1. ListBoxのアイテムを追加・削除する場合はObservableCollectionを使う
  2. 処理のおおまかな流れ
  3. 実施例
    1. XAML
    2. コード
    3. 動かしてみた

ListBoxに表示されるアイテムの追加と削除

ListBoxはユーザーにアイテムのリストを表示したり、選択してもらったりするコントロールです。表示するアイテムの変更が不要なら、表示するデータ(コレクション)をItemSourceに入れておけば良いのですが、ListBoxのアイテムを追加したり削除したりしたい場合があります。

ListBoxのアイテムを追加・削除する場合はObservableCollectionを使う

ListBoxにバインドするコレクションは、ObservableCollectionクラスにします。

ObservableCollectionにはCollectionChangedとPropertyChangedの2つのイベントが実装されていて、このコレクションを変更するとバインド先に通知してくれます。

自作のクラスにこれらのイベントを自分で実装することも出来ますが、ちょっと面倒です。

処理のおおまかな流れ

  1. データ格納用のクラスを作る。

  2. データ格納用のクラスのコレクションを、ObservableCollectionとして作る。

  3. ListBoxのItemSourceにコレクションをバインドする。

  4. コレクションに対して、アイテムを追加したり削除したりする。

実施例

XAML

<Window x:Class="WpfApp1.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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="200" Width="200" Loaded="Window_Loaded">
    <Grid>
        <StackPanel>
            <ListBox Name="listbox" ItemsSource="{Binding}" Height="100" SelectionMode="Multiple">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Path=Piyo}" />
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            <Button Name="buttonAdd" Content="Add" Click="ButtonAdd_Click" />
            <Button Name="buttonDel" Content="Delete" Click="ButtonDel_Click"  />
        </StackPanel>
    </Grid>
</Window>

コードの方で、データ保持用のクラスのコレクションをListBoxにバインドします。

データ保持用のクラスにPiyoというプロパティを設けていて、ListBoxの中のTextBlockのTextプロパティにデータ保持用クラスのPiyoプロパティをバインドします。

複数のアイテムを同時に削除するために、ListBoxのSelectionModeをMultipleにしました。

コード

コードは下記の様にしました。コードビハインドに書くのは美しくないらしいですが。

using System.Collections.ObjectModel;
using System.Windows;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        ObservableCollection<Hoge> hoges = new ObservableCollection<Hoge>(); // コレクションのインスタンスを作る。

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            listbox.ItemsSource = hoges; // コレクションをListBoxにバインドする。
        }

        private void ButtonAdd_Click(object sender, RoutedEventArgs e)
        {
            // ランダムな数字を作る。
            System.Random r = new System.Random();
            int i = r.Next(10);

            // ListBoxにアイテムを追加する。
            Hoge hoge = new Hoge();
            hoge.Piyo = "ぴよ" + i.ToString();
            hoges.Add(hoge);
        }

        private void ButtonDel_Click(object sender, RoutedEventArgs e)
        {
            if (hoges.Count < 1) return; // コレクションの数が0の場合は何もしない。

            // ListBoxで選択されたアイテムを、別のコレクションにコピーする。
            Collection<Hoge> selected = new Collection<Hoge>();
            foreach (Hoge i in listbox.SelectedItems)
            {
                selected.Add(i);
            }

            // 元のコレクションから、選択されたアイテムと同じアイテムを削除する。
            foreach (Hoge item in selected)
            {
                hoges.Remove(item);
            }
        }
    }
    public class Hoge
    {
        public string Piyo { get; set; }
    }
}

アイテムの追加については、単純にコレクションにAddするだけです。

アイテムの削除ですが、ListBox.SelectedItemsというコレクションを別の一時的なコレクションにコピーして、その一時的なコレクションのアイテムと一致するObservableCollectionのアイテムを削除します。これは、ObservableCollectionの方のコレクションからアイテムを1つRemoveするとその時点でListBox.SelectedItemsも変化するようで、foreachの対象となるコレクションが変化してしまって、foreachで2つ目のアイテムの処理ができなくなるからです。

動かしてみた

ビルドして実行して、「Add」ボタンを5回クリックしたところです。

image0

アイテムが5個追加されました。 「ぴよ2」と「ぴよ3」を選択します。

image1

そして「Delete」ボタンをクリックすると、「ぴよ2」と「ぴよ3」が削除されます。

image2

更新日
公開日

広告