WPF教程ListBox使用CheckBox和绑定数据

C#和WPF中的ListBox是ListBoxItems的集合。本教程中的代码示例演示了如何添加列表框项、将项添加到ListBox、从ListBox中删除项以及将ListBox绑定到数据源。

<ListBox></ListBox>

Width和Height属性表示ListBox的宽度和高度。Name属性表示控件的名称,它是控件的唯一标识符。Margin属性告诉ListBox在父控件上的位置。Horizo​​ntalAlignment和VerticalAlignment属性用于设置水平和垂直对齐方式。

以下代码片段设置ListBox控件的名称、高度和宽度。该代码还将水平对齐设置为左对齐,垂直对齐设置为顶部。

<ListBox Margin="10,10,0,13" Name="listBox1" HorizontalAlignment="Left" VerticalAlignment="Top" Width="194" Height="200" />

将项目添加到ListBox控件

ListBox控件是ListBoxItems的集合。下面的代码示例将项目集合添加到ListBox控件。

<ListBox Margin="10,10,0,13" Name="listBox1" HorizontalAlignment="Left" VerticalAlignment="Top" Width="194" Height="200">
    <ListBoxItem Content="Coffie"></ListBoxItem>
    <ListBoxItem Content="Tea"></ListBoxItem>
    <ListBoxItem Content="Orange Juice"></ListBoxItem>
    <ListBoxItem Content="Milk"></ListBoxItem>
    <ListBoxItem Content="Iced Tea"></ListBoxItem>
    <ListBoxItem Content="Mango Shake"></ListBoxItem>
</ListBox>

动态添加ListBox项,我们看到了如何在设计时从XAML将项目添加到ListBox。我们可以从代码中将项目添加到ListBox。

让我们更改我们的UI并向页面添加一个TextBox和一个按钮控件。TextBox和Button控件的XAML代码如下所示。

<TextBox Height="23" HorizontalAlignment="Left" Margin="8,14,0,0" Name="textBox1" VerticalAlignment="Top" Width="127" />
<Button Height="23" Margin="140,14,0,0" Name="button1" VerticalAlignment="Top" HorizontalAlignment="Left" Width="76" Click="button1_Click"> Add Item </Button>

最终的 UI 类似于图。

在按钮单击事件处理程序中,我们通过调用 ListBox.Items.Add 方法将 TextBox 的内容添加到 ListBox。以下代码将TextBox内容添加到ListBox项。

private void button1_Click(object sender, RoutedEventArgs e) {
    listBox1.Items.Add(textBox1.Text);

在按钮单击事件处理程序中,我们通过调用ListBox.Items.Add方法将TextBox的内容添加到ListBox。

现在,如果您在TextBox中输入文本并单击AddItem按钮,它会将TextBox的内容添加到ListBox。

删除列表框项目

我们可以使用ListBox.Items.Remove或ListBox.Items.RemoveAt方法从ListBox中的项目集合中删除一个项目。RemoveAt方法获取集合中项目的索引。

现在,我们修改我们的应用程序并添加一个名为DeleteItem的新按钮。此按钮的XAML代码如下所示。

<Button Height="23" Margin="226,14,124,0" Name="DeleteButton" VerticalAlignment="Top" Click="DeleteButton_Click"> Delete Item</Button>

按钮单击事件处理程序如下所示。单击此按钮,我们找到所选项目的索引并调用 ListBox.Items.RemoveAt 方法,如下所示。

private void DeleteButton_Click(object sender, RoutedEventArgs e) {
listBox1.Items.RemoveAt(listBox1.Items.IndexOf(listBox1.SelectedItem));

Formatting ListBox Items

ListBoxItem的Foreground和Background属性表示项目的背景色和前景色。以下代码片段设置ListBoxItem的背景和前景色。

<ListBoxItem Background="LightCoral" Foreground="Red" Content="Coffie"></ListBoxItem>

FontFamily、FontSize和FontWeight用于设置ListBoxItem的字体。以下代码片段设置ListBoxItem的字体verdana、大小12和粗体。

<ListBoxItem Background="LightCoral" Foreground="Red" Content="Coffie" FontFamily="Verdana" FontSize="12" FontWeight="Bold"></ListBoxItem>

我设置了ListBoxItems的以下属性。

<ListBoxItem Background="LightCoral" Foreground="Red" Content="Coffie" FontFamily="Verdana" FontSize="12" FontWeight="Bold"></ListBoxItem>
<ListBoxItem Background="LightGray" Foreground="Black" Content="Tea" FontFamily="Georgia" FontSize="14" FontWeight="Bold"></ListBoxItem>
<ListBoxItem Background="LightBlue" Foreground="Purple" Content="Orange Juice" FontFamily="Verdana" FontSize="12" FontWeight="Bold"></ListBoxItem>
<ListBoxItem Background="LightGreen" Foreground="Green" Content="Milk" FontFamily="Georgia" FontSize="14" FontWeight="Bold"></ListBoxItem>
<ListBoxItem Background="LightBlue" Foreground="Blue" Content="Iced Tea" FontFamily="Verdana" FontSize="12" FontWeight="Bold"></ListBoxItem>
<ListBoxItem Background="LightSlateGray" Foreground="Orange" Content="Mango Shake" FontFamily="Georgia" FontSize="14" FontWeight="Bold"></ListBoxItem>

在WPF列表框中加载图片

我们可以在ListBoxItem中放置任何控件,例如图片和文本。为了与一些文本并排显示图片 ,我只需在StackPanel中放置一个Image和TextBlock控件。Image.Source属性采用您希望在Image控件中显示的图片的名称,TextBlock.Text属性采用您希望在TextBlock中显示的字符串。

以下代码片段将图片和文本添加到ListBoxItem。

<ListBoxItem Background="LightCoral" Foreground="Red" FontFamily="Verdana" FontSize="12" FontWeight="Bold">
    <StackPanel Orientation="Horizontal">
        <Image Source="coffie.jpg" Height="30"></Image>
        <TextBlock Text="Coffie"></TextBlock>
    </StackPanel>
</ListBoxItem>

带有复选框的列表框

如果将CheckBox控件放在ListBoxItems中,则会生成一个带有复选框的ListBox控件。CheckBox也可以在其中托管控件。例如,我们可以将图像和文本块作为CheckBox的内容。

以下代码片段将带有图像和文本的CheckBox添加到ListBoxItem。

<ListBoxItem Background="LightCoral" Foreground="Red" FontFamily="Verdana" FontSize="12" FontWeight="Bold">
    <CheckBox Name="CoffieCheckBox">
        <StackPanel Orientation="Horizontal">
            <Image Source="coffie.jpg" Height="30"></Image>
            <TextBlock Text="Coffie"></TextBlock>
        </StackPanel>
    </CheckBox>
</ListBoxItem>

我更改了ListBoxItems的代码并将以下CheckBox添加到项目中。如您所见,我使用Name属性设置了CheckBox的名称。如果您需要访问这些CheckBox,您可以使用它们的Name属性在代码中访问它们。

<ListBoxItem Background="LightCoral" Foreground="Red" FontFamily="Verdana" FontSize="12" FontWeight="Bold">
    <CheckBox Name="CoffieCheckBox">
        <StackPanel Orientation="Horizontal">
            <Image Source="coffie.jpg" Height="30"></Image>
            <TextBlock Text="Coffie"></TextBlock>
        </StackPanel>
    </CheckBox>
</ListBoxItem>
<ListBoxItem Background="LightGray" Foreground="Black" FontFamily="Georgia" FontSize="14" FontWeight="Bold">
    <CheckBox Name="TeaCheckBox">
        <StackPanel Orientation="Horizontal">
            <Image Source="tea.jpg" Height="30"></Image>
            <TextBlock Text="Tea"></TextBlock>
        </StackPanel>
    </CheckBox>
</ListBoxItem>
<ListBoxItem Background="LightBlue" Foreground="Purple" FontFamily="Verdana" FontSize="12" FontWeight="Bold">
    <CheckBox Name="OrangeJuiceCheckBox">
        <StackPanel Orientation="Horizontal">
            <Image Source="OrangeJuice.jpg" Height="40"></Image>
            <TextBlock Text="OrangeJuice"></TextBlock>
        </StackPanel>
    </CheckBox>
</ListBoxItem>
<ListBoxItem Background="LightGreen" Foreground="Green" FontFamily="Georgia" FontSize="14" FontWeight="Bold">
    <CheckBox Name="MilkCheckBox">
        <StackPanel Orientation="Horizontal">
            <Image Source="Milk.jpg" Height="30"></Image>
            <TextBlock Text="Milk"></TextBlock>
        </StackPanel>
    </CheckBox>
</ListBoxItem>
<ListBoxItem Background="LightBlue" Foreground="Blue" FontFamily="Verdana" FontSize="12" FontWeight="Bold">
    <CheckBox Name="IcedTeaCheckBox">
        <StackPanel Orientation="Horizontal">
            <Image Source="IcedTea.jpg" Height="30"></Image>
            <TextBlock Text="Iced Tea"></TextBlock>
        </StackPanel>
    </CheckBox>
</ListBoxItem>
<ListBoxItem Background="LightSlateGray" Foreground="Orange" FontFamily="Georgia" FontSize="14" FontWeight="Bold">
    <CheckBox Name="MangoShakeCheckBox">
        <StackPanel Orientation="Horizontal">
            <Image Source="MangoShake.jpg" Height="30"></Image>
            <TextBlock Text="Mango Shake"></TextBlock>
        </StackPanel>
    </CheckBox>
</ListBoxItem>

ListBox控件中的数据绑定

.NET3.0和3.5中将数据绑定搞得一团糟。他们没有让事情变得更简单,而是让事情变得复杂。也许他们在未来有一些更大的计划,但到目前为止,我已经看到使用依赖对象和属性、LINQ和LINQ、 WCF和ASP.NET Web服务进行绑定,这一切看起来都是一团糟。它甚至不接近我们在 .NET1.0和2.0中的ADO.NET模型。我希望他们能在不久的将来收拾这个烂摊子。

ListBox的ItemsSource属性用于将IEnumerable的集合(例如ArrayList)绑定到ListBox控件。

LeftListBox.ItemsSource = LoadListBoxData();
private ArrayList LoadListBoxData() {
    ArrayList itemsList = new ArrayList();
    itemsList.Add("Coffie");
    itemsList.Add("Tea");
    itemsList.Add("Orange Juice");
    itemsList.Add("Milk");
    itemsList.Add("Mango Shake");
    itemsList.Add("Iced Tea");
    itemsList.Add("Soda");
    itemsList.Add("Water");
    return itemsList;

将数据从一个ListBox传输到另一个

我们已经看到了很多要求,其中一个页面有两个ListBox控件,而左边的ListBox显示一个项目列表。使用按钮我们可以从左侧ListBox添加项目并将它们添加到右侧ListBox,使用删除按钮我们可以从右侧ListBox删除项目并将它们添加回左侧ListBox。

此示例显示了我们如何将项目从一个ListBox移动到另一个。最终页面如图7所示。Add按钮将所选项目添加到右侧ListBox并从左侧ListBox中删除。Remove按钮从右侧ListBox中删除所选项目并添加回左侧ListBox。

<ListBox Margin="11,13,355,11" Name="LeftListBox" />
<ListBox Margin="0,13,21,11" Name="RightListBox" HorizontalAlignment="Right" Width="216" />
<Button Name="AddButton" Height="23" Margin="248,78,261,0" VerticalAlignment="Top" Click="AddButton_Click">Add >></Button>
<Button Name="RemoveButton" Margin="248,121,261,117" Click="RemoveButton_Click"><< Remove</Button>

在Window加载事件中,我们通过将ItemsSource属性设置为ArrayList来创建数据项并将其加载到ListBox。

private void Window_Loaded(object sender, RoutedEventArgs e) {
    myDataList = LoadListBoxData();
    // Bind ArrayList with the ListBox
    LeftListBox.ItemsSource = myDataList;
private ArrayList LoadListBoxData() {
    ArrayList itemsList = new ArrayList();
    itemsList.Add("Coffie");
    itemsList.Add("Tea");
    itemsList.Add("Orange Juice");
    itemsList.Add("Milk");
    itemsList.Add("Mango Shake");
    itemsList.Add("Iced Tea");
    itemsList.Add("Soda");
    itemsList.Add("Water");
    return itemsList;

在添加按钮单击事件处理程序中,我们在左侧ListBox中获取所选项目的值和索引,并将其添加到右侧ListBox并从作为我们的数据源的ArrayList中删除该项目。ApplyBinding方法只是删除ListBox的当前绑定并与更新的ArrayList重新绑定。

private void AddButton_Click(object sender, RoutedEventArgs e) {
    // Find the right item and it's value and index
    currentItemText = LeftListBox.SelectedValue.ToString();
    currentItemIndex = LeftListBox.SelectedIndex;
    RightListBox.Items.Add(currentItemText);
    if (myDataList != null) {
        myDataList.RemoveAt(currentItemIndex);
    // Refresh data binding
    ApplyDataBinding();
///<summary>
/// Refreshes data binding
///</summary>
private void ApplyDataBinding() {
    LeftListBox.ItemsSource = null;
    // Bind ArrayList with the ListBox
    LeftListBox.ItemsSource = myDataList;

同样,在“删除”按钮单击事件处理程序上,我们从右侧ListBox获取所选项目文本和索引,并将其添加到ArrayList并从右侧ListBox中删除。

private void RemoveButton_Click(object sender, RoutedEventArgs e)
    // Find the right item and it's value and index
    currentItemText = RightListBox.SelectedValue.ToString();
    currentItemIndex = RightListBox.SelectedIndex;
    // Add RightListBox item to the ArrayList
    myDataList.Add(currentItemText);
    RightListBox.Items.RemoveAt(RightListBox.Items.IndexOf(RightListBox.SelectedItem));
    // Refresh data binding
    ApplyDataBinding();

与数据库的数据绑定

我们使用SQLServer自带的Northwind.mdf数据库。在我们的应用程序中,我们将从客户表中读取数据。客户表列如图所示。

我们将读取WPF ListBox控件中的ContactName、Address、City和Country列。最终的ListBox类似于下图。

现在让我们看看我们的XAML文件。我们创建名为listBoxTemplate的资源DataTemplate类型。数据模板用于以格式化的方式表示数据。数据模板有两个停靠面板,其中第一个面板显示名称,第二个面板使用TextBlock控件显示地址、城市和国家/地区列。

<Window.Resources>
    <DataTemplate x:Key="listBoxTemplate">
        <StackPanel Margin="3">
            <DockPanel>
                <TextBlock FontWeight="Bold" Text="Name:" DockPanel.Dock="Left" Margin="5,0,10,0" />
                <TextBlock Text="" />
                <TextBlock Text="{Binding ContactName}" Foreground="Green" FontWeight="Bold" />
            </DockPanel>
            <DockPanel>
                <TextBlock FontWeight="Bold" Text="Address:" Foreground="DarkOrange" DockPanel.Dock="Left" Margin="5,0,5,0" />
                <TextBlock Text="{Binding Address}" />
                <TextBlock Text=", " />
                <TextBlock Text="{Binding City}" />
                <TextBlock Text=", " />
                <TextBlock Text="{Binding Country}" />
            </DockPanel>
        </StackPanel>
    </DataTemplate>
</Window.Resources>

现在我们添加一个ListBox控件并将其ItemsSource属性设置为DataSet的第一个DataTable并将ItemTemplate设置为上面定义的资源。

<ListBox Margin="17,8,15,26" Name="listBox1" ItemsSource="{Binding Tables[0]}" ItemTemplate="{StaticResource listBoxTemplate}" />

现在在我们后面的代码中,我们定义了以下变量。

public SqlConnection connection;
public SqlCommand command;
string sql = "SELECT ContactName, Address, City, Country FROM Customers";
string connectionString = @ "Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\NORTHWND.MDF;Integrated Security=True;Connect Timeout=30;User Instance=True";

现在在 Windows_Loaded 方法中,我们调用 BindData 方法,在 BindData 方法中,我们创建一个连接、数据适配器,并使用 SqlDataAdapter.Fill() 方法填充 DataSet。

private void Window_Loaded(object sender, RoutedEventArgs e) {
    BindData();
private void BindData() {
    DataSet dtSet = new DataSet();
    using(connection = new SqlConnection(connectionString)) {
        command = new SqlCommand(sql, connection);
        SqlDataAdapter adapter = new SqlDataAdapter();
        connection.Open();
        adapter.SelectCommand = command;
        adapter.Fill(dtSet, "Customers");
        listBox1.DataContext = dtSet;

与 XML 的数据绑定

现在让我们看看如何将XML数据绑定到ListBox控件。XmlDataProvider用于在WPF中绑定XML数据。

这是在XAML中定义的包含书籍数据的XmlDataProvider。XML数据在x:Data标记中定义。

<XmlDataProvider x:Key="BooksData" XPath="Inventory/Books">
    <x:XData>
        <Inventory xmlns="">
            <Books>
                <Book Category="Programming">
                    <Title>A Programmer's Guide to ADO.NET</Title>
                    <Summary>Learn how to write database applications using ADO.NET and C#. </Summary>
                    <Author>Mahesh Chand</Author>
                    <Publisher>APress</Publisher>
                </Book>
                <Book Category="Programming">
                    <Title>Graphics Programming with GDI+</Title>
                    <Summary>Learn how to write graphics applications using GDI+ and C#. </Summary>
                    <Author>Mahesh Chand</Author>
                    <Publisher>Addison Wesley</Publisher>
                </Book>
                <Book Category="Programming">
                    <Title>Visual C#</Title>
                    <Summary>Learn how to write C# applications. </Summary>
                    <Author>Mike Gold</Author>
                    <Publisher>APress</Publisher>
                </Book>
                <Book Category="Programming">
                    <Title>Introducing Microsoft .NET</Title>
                    <Summary>Programming .NET </Summary>
                    <Author>Mathew Cochran</Author>
                    <Publisher>APress</Publisher>
                </Book>
                <Book Category="Database">
                    <Title>DBA Express</Title>
                    <Summary>DBA's Handbook </Summary>
                    <Author>Mahesh Chand</Author>
                    <Publisher>Microsoft</Publisher>
                </Book>
            </Books>
        </Inventory>
    </x:XData>
</XmlDataProvider>

要绑定XmlDataProvider,我们将ListBox的ItemsSource内的Source属性设置为XmlDataProvider的x:Key,XPath用于过滤数据。在ListBox.ItemTempate中,我们使用Binding属性。

ListBox Width="400" Height="300" Background="LightGray">
    <ListBox.ItemsSource>
        <Binding Source="{StaticResource BooksData}" XPath="*[@Category='Programming'] " />
    </ListBox.ItemsSource>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Title: " FontWeight="Bold" />
                <TextBlock Foreground="Green">
                    <TextBlock.Text>
                        <Binding XPath="Title" />
                    </TextBlock.Text>
                </TextBlock>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

与控件的数据绑定

我们将看到的最后一个数据绑定类型是如何使用WPF中的数据绑定在ListBox和其他控件之间提供数据交换。

我们将创建一个应用程序。我有一个带有颜色列表的ListBox、一个TextBox和一个Canvas。当我们从ListBox中选择一种颜色时,TextBox的文本和Canvas的颜色会动态地更改为在ListBox中选择的颜色,这可以在XAML中完成,而无需在代码隐藏文件中编写一行代码。

<StackPanel Orientation="Vertical">
    <TextBlock Margin="10,10,10,10" FontWeight="Bold"> Pick a color from below list </TextBlock>
    <ListBox Name="mcListBox" Height="100" Width="100" Margin="10,10,0,0" HorizontalAlignment="Left">
        <ListBoxItem>Orange</ListBoxItem>
        <ListBoxItem>Green</ListBoxItem>
        <ListBoxItem>Blue</ListBoxItem>
        <ListBoxItem>Gray</ListBoxItem>
        <ListBoxItem>LightGray</ListBoxItem>
        <ListBoxItem>Red</ListBoxItem>
    </ListBox>
    <TextBox Height="23" Name="textBox1" Width="120" Margin="10,10,0,0" HorizontalAlignment="Left">
        <TextBox.Text>
            <Binding ElementName="mcListBox" Path="SelectedItem.Content" />
        </TextBox.Text>
    </TextBox>