【WPF学习】第二十三章 列表控件
WPF提供了许多封装项的集合的控件,本章介绍简单的ListBox和ComboBox控件,后续哈会介绍更特殊的控件,如ListView、TreeView和ToolBar控件。所有这些控件都继承自ItemsControl类(ItemsControl类本身又继承自Control类)。
ItemsControl类添加了所有基于列表的控件都使用的基本功能。最显著的是,它提供了填充列表项的两种方式。最直接的方法是代码或XAML将列表项直接添加到Items集合中。然而,在WPF中使用数据绑定的方法更普遍。使用数据绑定方法,需将ItemsSource属性设置为希望显示的具有数据项集合的对象(后续章节介绍与列表数据绑定相关的更多内容)。
ItemsControl类之后的继承橙子有些混乱。一个主要分支是选择器(selector),包括ListBox、ComboBox以及TabControl。这些控件都继承自Selector类,并且都具有跟踪当前选择项(SelectedItem)或其位置(SelectedIndex)的属性,封装列表项的控件是另一个分支,以不同方式选择列表项。该分支包括用于菜单、工具栏以及树的类——所有这些类都属于ItemsControl,但不是选择器。
为了充分发挥所有ItemsControl控件的功能,需要使用数据绑定。即使不从数据库甚至外部数据源获取数据,也同样如此。WPF数据绑定非常普遍,可使用各种数据,包括自定义的数据对象和集合。但现在还不需要考虑数据绑定的细节。现在,先快速浏览一下ListBox控件和ComboBox控件。
一、ListBox
ListBox类代表了一种最常用的Windows设计——允许用户从长度可变的列表中选择一项。
如果将SelectionMode属性设置为Multiple或Extended,ListBox类还允许选择多项。在Multiple模式下,可通过单击项进行选择或取消选择。在Extended模式下,需要按下Ctrl键选择其他项,或按下Shift键选择某个选项范围。在这两种多选模式下,可用SelectedItems集合替代SelectedItem属性来获取所有选择的项。
为向ListBox控件中添加项,可在ListBox元素中嵌套ListBoxItem元素。例如,下面是一个包含颜色列表的ListBox:
<ListBox>
<ListBoxItem>Yellow</ListBoxItem>
<ListBoxItem>Blue</ListBoxItem>
<ListBoxItem>Green</ListBoxItem>
<ListBoxItem>Red</ListBoxItem>
<ListBoxItem>LightBlue</ListBoxItem>
<ListBoxItem>Black</ListBoxItem>
</ListBox>
不同控件采用不同方式处理嵌套的内容。ListBox控件在它的Items集合中存储每个嵌套的对象。
ListBox控件是一个非常灵活的控件。它不仅可以包含ListBoxItem对象,也可以驻留其他任意元素。这是因为ListBoxItem类继承自ContentControl类,从而ListBoxItem能够包含一段嵌套的内容。如果该内容继承自UIElement类,它将ListBox控件中呈现出来。如果是其他类型的对象,ListBoxItem对象会调用ToString()方法并显示最终的文本。
例如,如果决定创建一个包含图像的列表,可使用如下标记:
<ListBox>
<ListBoxItem>
<Image Source="happyface.jpg"></Image>
</ListBoxItem>
<ListBoxItem>
<Image Source="redx.jpg"></Image>
</ListBoxItem>
</ListBox>
实际上ListBox控件足够职能,它能隐式地创建所需的ListBoxItem对象。这意味着可直接在ListBox元素中放置对象。厦门市一个更复杂的示例,该示例使用嵌套的StackPanel对象组合文本和图像内容:
<Window x:Class="Controls.ImageList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ImageList" Height="300" Width="300">
<ListBox Margin="5" SelectionMode="Multiple" Name="lst" SelectionChanged="lst_SelectionChanged">
<StackPanel Orientation="Horizontal">
<Image Source="happyface.jpg" Width="30" Height="30"></Image>
<Label VerticalAlignment="Center">A Happy face</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Image Source="redx.jpg" Width="30" Height="30"></Image>
<Label VerticalAlignment="Center">A Warning face</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Image Source="happyface.jpg" Width="30" Height="30"></Image>
<Label VerticalAlignment="Center">A Happy face</Label>
</StackPanel>
</ListBox>
</Window>
ImageListBox
在该例中,StackPanel面板变成被ListBoxItem封装的项。该标记创建的富列表如图下图所示:

利用在列表框中的嵌套任意元素的能力,可创建出各种基于列表的控件,而不必使用其他类。例如,Windows窗体的哦该凝聚项中CheckedListBox类,该类显示在每个项的旁边都具有复选框的列表。在WPF中不需要这一特殊类,因为完全可使用标准的ListBox控件快速构建相同的效果:
<Window x:Class="Controls.CheckBoxList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CheckBoxList" Height="300" Width="300">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions> <ListBox Name="lst" SelectionChanged="lst_SelectionChanged"
CheckBox.Click="lst_SelectionChanged" >
<CheckBox Margin="3">Option 1</CheckBox>
<CheckBox Margin="3">Option 2</CheckBox>
<CheckBox Margin="3">Option 3</CheckBox>
</ListBox>
<StackPanel Grid.Row="1" Margin="0,10,0,0">
<TextBlock>Current selection:</TextBlock>
<TextBlock Name="txtSelection" TextWrapping="Wrap"></TextBlock>
<Button Margin="0,10,0,0" Click="cmd_CheckAllItems">Examine All Items</Button>
</StackPanel>
</Grid>
</Window>
CheckBoxList
当在列表内部使用不同元素时需要注意一点。当读取SelectedItem值时(以及SelectedItems和Items集合),看不到ListBoxItem对象——反而将看到放入到列表中的对象。在CheckedListBox示例中,这意味着SelectedItem提供了CheckBox对象。
例如,下面是一些响应SelectionChanged事件触发的代码。这些代码获取当天选中CheckBox对象并显示该项是否被选中:
private void lst_SelectionChanged(object sender, RoutedEventArgs e)
{
// Select when checkbox portion is clicked (optional).
if (e.OriginalSource is CheckBox)
{
lst.SelectedItem = e.OriginalSource;
} if (lst.SelectedItem == null) return;
txtSelection.Text = String.Format(
"You chose item at position {0}.\r\nChecked state is {1}.",
lst.SelectedIndex,
((CheckBox)lst.SelectedItem).IsChecked);
}
在下面的代码片段中,类似的代码遍历选项集合以确定哪一项被选中(对于使用复选框的多项选择列表,可以编写类似的代码来遍历选中项的集合)。
private void cmd_CheckAllItems(object sender, RoutedEventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach (CheckBox item in lst.Items)
{
if (item.IsChecked == true)
{
sb.Append(
item.Content + " is checked.");
sb.Append("\r\n");
}
}
txtSelection.Text = sb.ToString();
}
最终效果如下所示:

在列表框中手动放置项时,由你决定是希望直接插入项还是在ListBoxItem对象中明确地包含每项。第二种方法通常更清晰,也更繁琐。最重要的考虑事项是一致性。例如,如果在列表中放置StackPanel对象,ListBox.SelectedItem对象将是StackPanel。如果放置由ListBoxItem对象封装的StackPanel对象,ListBox.SelectedItem对象将是ListBoxItem,所以可进行响应编码。
ListBoxItem提供了少许额外功能,通过这些功能可得到直接嵌套的对象。换言之,ListBoxItem定义了可以读取(或设置)的IsSelected属性,以及用于通知何时选中的Selected和Unselected事件。然而,可使用ListBox类的成员得到类似功能,如SelectedItem属性(或SelectedItems属性)以及SelectionChanged事件。
有趣的是,当使用嵌套对象方法时,有一项技术可为特定的对象检索ListBoxItem封装器。技巧是使用常被忽视的ContainerFromElement()方法。下面的代码使用该技术检查列表中的第一个条目是否被选中:
ListBoxItem item=(ListBoxItem)lst.ContainerFromElement((DependencyObject)lst.SelectedItems[]);
MessageBox.Show("IsSelected:"+item.IsSelected.ToString());
二、ComboBox
ComboBox控件和ListBox控件类似。该控件包含ComboBoxItem对象的集合,既可以显示地也可以隐式地创建该集合。与ListBoxItem类似,ComboBoxItem也是可以包含任意嵌套元素的内容控件。
ComboBox类和ListBox类之间的重要区别是他们在窗口中呈现自身的方式。Combox控件使用下拉列表,这意味着一次只能选择一项。
如果希望允许用户在组合框中通过输入文本选项一项,就必须将IsEditable属性设置为true,并且必须确保选项集合中存储的是普遍的纯文本的ComboBoxItem对象,或是提供了有意义的ToString()表示的对象。例如,如果使用Image对象填充可编辑的组合框,那么在上面显示的文本将只有Image类的全名,这用处不大。
ComboBox控件的局限之一在于当使用自动改变尺寸功能时该控件改变自身尺寸的方法。ComboBox控件加宽自身以适应它的内容,这意味着当从一项移到另一项是它会改变自身大小。但没有简便的方法告诉ComboBox控件使用包含项的最大尺寸。相反,需要为Width属性提供硬编码的值,而这并不理想。
下面是一个简单的示例:
<Window x:Class="Controls.ComboBoxTest"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ComboBoxTest" Height="300" Width="300">
<StackPanel>
<ComboBox Margin="5">
<StackPanel Orientation="Horizontal">
<Image Source="happyface.jpg" Width="30" Height="30"></Image>
<Label VerticalAlignment="Center">A Happy face</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Image Source="redx.jpg" Width="30" Height="30"></Image>
<Label VerticalAlignment="Center">A Warning face</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Image Source="happyface.jpg" Width="30" Height="30"></Image>
<Label VerticalAlignment="Center">A Happy face</Label>
</StackPanel>
</ComboBox>
</StackPanel>
</Window>
ComboBoxTest
最终效果图如下所示:


【WPF学习】第二十三章 列表控件的更多相关文章
- WP8.1学习系列(第二十三章)——到控件的数据绑定
在本文中 先决条件 将控件绑定到单个项目 将控件绑定到对象的集合 通过使用数据模板显示控件中的项目 添加详细信息视图 转换数据以在控件中显示 相关主题 本主题介绍了如何在使用 C++.C# 或 Vis ...
- WPF自定义控件与样式(7)-列表控件DataGrid与ListView自定义样式
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Dat ...
- 【转】WPF自定义控件与样式(7)-列表控件DataGrid与ListView自定义样式
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要内容: DataGrid自定义样式: ListView自定义样式: 二.Dat ...
- WPF学习(一)--布局控件简介
WPF的4种基本布局介绍 1.Grid的布局 这个就没啥特别好说的,其实,基本上复杂的布局,都需要用到Grid. 主要就是对行和列进行进行设置和定义. 1.行表格 列表格: 包含行和列的表格 2.St ...
- WPF自定义控件与样式(9)-树控件TreeView与菜单Menu-ContextMenu
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: 菜单M ...
- WPF自定义控件与样式(10)-进度控件ProcessBar自定义样
一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接. 本文主要内容: Pro ...
- 【WPF学习】第五十九章 理解控件模板
最近工作比较忙,未能及时更新内容,敬请了解!!! 对于可视化树的分析引出了几个有趣问题.例如,控件如何从逻辑树表示扩张成可视化树表示? 每个控件都有一个内置的方法,用于确定如何渲染控件(作为一组更基础 ...
- 【WPF开发备忘】使用MVVM模式开发中列表控件内的按钮事件无法触发解决方法
实际使用MVVM进行WPF开发的时候,可能会用到列表控件中每行一个编辑或删除按钮,这时直接去绑定,发现无法响应: <DataGridTemplateColumn Header="操作& ...
- 第三部分:Android 应用程序接口指南---第二节:UI---第二章 输入控件
第2章 输入控件 输入控件是应用程序中用户接口的一种交互式组件.Android提供了大量的可供人们在UI中使用的控件,比如按钮.文本区域.(带滑块的)进度条.复选框.缩放按钮以及切换按钮等等. 在UI ...
随机推荐
- UI 素材相关收集
图标素材收藏网址 阿里:iconfont.cn 图片压缩:https://tinypng.com/ gif动图压缩:https://tool.gifhome.com
- 使用IDEA创建基于Maven SpringMvc项目
使用IDEA创建基于Maven SpringMvc项目 1.通过程序启动——create project,或者file--New-projec打开New project 2.自定义groupid等信息 ...
- 【Linux】Ubuntu16.04 ftp匿名访问
一.安装: 1.安装命令: sudo apt-get install vsftpd 2.配置文件: vi /etc/vsftpd.conf 3.开启.关闭.重启服务 sudo /etc/init.d/ ...
- 【Linux】nl笔记
nl命令在linux系统中用来计算文件中行号.nl 可以将输出的文件内容自动的加上行号!其默认的结果与 cat -n 有点不太一样, nl 可以将行号做比较多的显示设计,包括位数与是否自动补齐 0 等 ...
- 对“TD信息树”的使用体验
在本次同2017级学长进行的软件交流会上,我们有幸使用学长们开发的软件与成果,进过27个不尽相同的软件的使用,让我初步意识到了学习软件工程这门学科的实用价值.最终我选择了"TD信息树&quo ...
- JDK、JRE、JVM、Android SDK、Android Studio
===================================================== 参考链接: JDK\JRE\JVM:https://www.cnblogs.com/bola ...
- python类方法、类属性和静态方法
class Game(object): #类属性 num = 0 #实例方法 def __init__(self): #实例属性 self.name = "laowang" #类方 ...
- java中如何自动获取电脑的ip地址
String ip=InetAddress.getLocalHost().getHostAddress().toString(); 可以写一个main方法测试一下.
- 菜鸟系列Fabric源码学习 — MVCC验证
Fabric 1.4 源码分析 MVCC验证 读本节文档之前建议先查看[Fabric 1.4 源码分析 committer记账节点]章节. 1. MVCC简介 Multi-Version Concur ...
- 非常完整的线性DP及记忆化搜索讲义
基础概念 我们之前的课程当中接触了最基础的动态规划. 动态规划最重要的就是找到一个状态和状态转移方程. 除此之外,动态规划问题分析中还有一些重要性质,如:重叠子问题.最优子结构.无后效性等. 最优子结 ...