Home > C# > WPF > WPFコントロール > Listbox > DataBindingを使用して、選択した要素をTextBoxに表示する

WPFのListBoxで、DataBindingを使用して、選択した要素をTextBoxに表示する

新規作成日 2019-02-09
最終更新日

ListBoxの選択した要素の内容を他のコントールに表示する場合、WPFでは、xaml内でデータ結合を使用することで、C#コードを記述せずに実現することができます。

UI内部の動きをxamlコード内で完結することで、分離コードに記述するC#コードの量が減り、C#コードが見やすくなります。その結果、C#コードを修正することなく、xaml側の変更だけで、UIを変更できます。一方、その分、xamlコードが増えるので、どちらが良いのかは、一概に判断できません。

ListBoxItemで追加した項目を扱う

xamlコード内で、ListBox内に項目をListBoxItem要素として追加する場合、追加された項目は、ListBoxItemクラスです。そのため、ListBoxに、String型の要素を追加した場合とは扱いが異なります。

C# WPFのListBoxで、データ結合を使用して、選択した要素をTextBlockに表示する

ListBox内で項目を選択したとき、上のTextBlockには、ListBoxのSelectItemが、下のTextBlockには、ListBoxのSelectItem.Contentが表示されます。

MainWindow.xaml

<Window x:Class="ListBoxBinding01.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="MainWindow" Height="200" Width="300">

    <DockPanel>
        <TextBlock DockPanel.Dock="Top" Name="ListItem" Height="30" Padding="5,0,0,0"
                 Text="{Binding ElementName=Listbox01, Path=SelectedItem}"/>
        <TextBlock DockPanel.Dock="Top" Name="ListItemName" Height="30" Padding="5,0,0,0"
                 Text="{Binding ElementName=Listbox01, Path=SelectedItem.Content}"/>
        
        <ListBox DockPanel.Dock="Bottom" Name="Listbox01" SelectionMode="Single">
            <ListBoxItem Content="みかん"/>
            <ListBoxItem Content="りんご"/>
            <ListBoxItem>ばなな</ListBoxItem>
        </ListBox>
    </DockPanel>

</Window>

このコードは、xamlコードで書かれています。xamlコードは、xmlと呼ばれる記述方法に従って、UIを定義する方法です。

Windowタグの中に、DockPanelタグ、その中に、TextBlockタグとListBoxタグが入っています。

これらのそれぞれは、UIを示しており、Windowsタグが、キャプション(この例では、MainWindow)を含む、ウィンドウを表しています。続く、DockPanelは、レイアウト・パネルやレイアウト・コンテナと呼ばれ、この中に入れ子にするコントロールの配置方法を決定するパネルです。

この例では、DockPanelの中に、TextBlockが2つ、ListBoxが1つ入っています。この状態を「入れ子」や「ネスト」と表現します。DockPanelは、入れ子になった要素を指定した端部(DockPanel.Dock属性で、指定する既定はTop)から、順番に並べていき、最後の要素に残った領域を割り当てます。そのため、この例では、何も指定していなのに、ListBoxが、TextBlockより大きな領域が割り当てられています。

ListBoxでは、 DockPanel.Dock属性、Name属性、SelectionMode属性が指定されています。

DockPanel.Dock属性は、先程説明したDockPanelの配置する端部の位置を指定しています。

Name属性は、コントールを識別するために名前です。このコントロールを対象に何か行うとき、Name属性で、指定します。

SelectionMode属性は、ListBoxの選択モードを指定します。この例では、Singleを指定し、項目を1つしか選択出来ないようにしています。

ListBox内で、項目を指定する際は、ListBoxItemコントロールを使用します。内容は、Content属性に指定する方法と

<ListBoxItem Content="みかん"/>

開始タグと終了タグの間に記述する方法があります。

<ListBoxItem>ばなな</ListBoxItem>

TextBlockで、DockPanel.Dock属性、Name属性、Height属性、Padding属性、Text属性を指定しています。

Padding属性は、コントロール内に記述する位置を指定します。TextBlockでは、文字を記述する位置です。何も指定しない場合、左に文字が寄りすぎて、見えにくかったので、指定しています。

Text属性は、TextBlockで表示する文字を指定します。通常、文字列で指定します。今回の例は、データ結合の例なので、データ結合で指定しています。

Text="{Binding ElementName=Listbox01, Path=SelectedItem}"

ElementNameは、データ結合するコントールのName属性を指定します。

Pathは、データ結合するデータを指定します。

Text属性は、String型のデータを要求するので、「SelectItem」のようにObject型を指定すると、自動で型変換が実行されます。今回の場合は、おそらく、ToStringメソッド。そのため、ListBoxの項目「みかん」を指定するとTextBlockには、ListBoxの項目として、表示されている値とは異なる値、「System.Windows.Controls.ListBoxItem:みかん」と表示されます。

「みかん」と表示するには、Passに、「SelectedItem」ではなく、「SelectedItem.Content」と指定します。

Text="{Binding ElementName=Listbox01, Path=SelectedItem.Content}"

C#コードからListBoxにString型の要素を追加する

C#コードからListBoxに項目を追加するコードを探すと、String型の要素を追加する例が見つかります。

しかし、xamlコード内で、ListBox内に項目をListBoxItem要素を追加し、更に、C#コードで、String型の要素を追加すると、ListBox内の要素を表示する際に問題が生じます。

xamlコードはそのままで、分離コードを以下のように変更します。

MainWindow.xaml.cs

using System.Windows;

namespace ListBoxBinding01
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            // リストの初期値を入力
            SetInitialListItems();
        }
        private void SetInitialListItems()
        {
            Listbox01.Items.Add("もも");
            Listbox01.Items.Add("いちご");
            Listbox01.Items.Add("ぶどう");
        }
    }
}
C#で追加した項目の挙動
データ結合で表示される内容
SelectedItem SelectedItem.Content
System.Windows.Controls.ListBoxItem: みかん みかん
System.Windows.Controls.ListBoxItem: りんご りんご
System.Windows.Controls.ListBoxItem: ばなな ばなな
もも
いちご
ぶどう

ListBoxに表示される内容を表示したい場合、「SelectedItem」、「SelectedItem.Content」で表示すると、xamlコード内で、ListBox内に、ListBoxItem要素で追加した項目と、C#コードで、String型の要素として追加した項目で表示される内容が異なるので、ListBox内の項目に混在させる場合は、注意が必要です。

C#コードからListBoxItem要素を追加する

簡単な解決策は、ListBoxに追加する項目の型を統一することです。

C#コードでも、ListBoxItem要素として、ListBoxを追加することで、ListBox内の要素を表示することが簡単になります。

MainWindow.xaml
<Window x:Class="ListBoxDataBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="300">

    <DockPanel>
        <TextBlock DockPanel.Dock="Top" Name="ListItem" Height="30" Padding="5,0,0,0"
                 Text="{Binding ElementName=Listbox01, Path=SelectedItem}"/>
        <TextBlock DockPanel.Dock="Top" Name="ListItemName" Height="30" Padding="5,0,0,0"
                 Text="{Binding ElementName=Listbox01, Path=SelectedItem.Content}"/>

        <ListBox DockPanel.Dock="Bottom" Name="Listbox01" SelectionMode="Single">
            <ListBoxItem Content="みかん"/>
            <ListBoxItem Content="りんご"/>
            <ListBoxItem>ばなな</ListBoxItem>
        </ListBox>
    </DockPanel>

</Window>
MainWindow.xaml.cs
using System.Windows;
using System.Windows.Controls;

namespace ListBoxDataBinding
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            // リストの初期値を入力
            SetInitialListItems();
        }
        private void SetInitialListItems()
        {
            AddListBoxItem("もも");
            AddListBoxItem("いちご");
            AddListBoxItem("ぶどう");
        }
        private void AddListBoxItem(string strItem)
        {
            ListBoxItem myItem = new ListBoxItem();
            myItem.Content = strItem;

            Listbox01.Items.Add(myItem);
        }
    }
}
C#コードからListBoxItem要素を追加する

参考資料

関連ページ

このエントリーをはてなブックマークに追加

Home PC C# Illustration

Copyright (C) 2011 Horio Kazuhiko(kukekko) All Rights Reserved.
kukekko@gmail.com
ご連絡の際は、お問い合わせページのURLの明記をお願いします。
「掲載内容は私自身の見解であり、所属する組織を代表するものではありません。」