Expression Blend 和 Silverlight 中的 ListBox 样式(第 3 部分 - 附加模板)





5.00/5 (37投票s)
ListBox 附加模板和生成内容的解释和示例。涵盖布局、过渡和动画。
引言
欢迎阅读我的第七个 Expression Blend 和 Silverlight 初学者教程。这次,我们将通过附加模板查看ListBox生成内容的样式设置,我将尽力指导您完成此操作。
再次重申,在开始本教程之前,我建议您阅读我以前的 CodeProject 教程。我正在将它们作为系列教程编写,因此,本教程将假定您已具备先前的知识。
- 第 1 课 - 制作更好的按钮(初学者指南)
- 第 2 课 - 街机按钮(如何在控件模板中控制元素的位置)
- 第 3 课 - 相框控件(什么是控件,为什么要使用它?)
- 第 4 课 - 最后一次制作按钮(WC门按钮,以及所有 10 个按钮的下载)
- 第 5 课 - ListBox 样式设置 - 滚动条(本教程的第 1 部分)
- 第 6 课 - ListBox 样式设置 - 控件模板(本教程的第 2 部分)
我们目前涵盖了哪些内容?
在本教程的上一部分中,我们讨论了控件模板以及它如何有效地构成 ListBox
的边框/框架/舞台。我们对这些元素(主要是 ScrollViewer
)进行了样式设置,以适应 ListBox
的预期用途/环境,无论它们是什么……我也不知道,所以我给应用程序添加了一个框架以提供一些上下文。但是如果我们回顾一下之前的教程,我们会发现这只是强调了 ListBox
和 TreeView
的内容并没有真正匹配新的 Style
。
TreeView
中的黄色文件夹图标与颜色方案不符,ListBox
中的蓝色超链接文本也不符。此外,当应用程序运行时,文件和文件夹的鼠标悬停状态是淡蓝色。以及 ListBox
上溢出到边框面板(ScrollContentPresenter
)之外的矩形选择区域。现在,ListBox
控件模板中的任何内容都不会对我刚刚提出的问题产生任何影响。原因是控件模板与 ListBox
、TreeView
(或任何其他 Control
)的生成内容无关。它所做的只是设置 Control
的舞台(框架/边框)并容纳 ScrollContentPresenter
,后者是通往生成内容这个虚构世界的门户。我称之为虚构,因为如果没有内容,它都是隐形的!所以感谢你可能祈祷的任何人提供的示例数据,因为它对于设计生成内容的 UI 来说确实非常棒。另外,你可以与你的开发人员交谈,他们可以创建特定的设计时示例数据源,就像 defwebserver 在这里所做的一样。
附加模板快速概述
让我们看看 ListBox
的附加模板,并尝试理解每个模板的作用。
基本上,我们有三个额外的模板,它们控制和操作出现在 ScrollContentPresenter
中的生成内容。每个模板在呈现和格式化生成内容和数据方面都有不同的作用或目标。下面是一个面向 UI 设计师的模板关系简化图。
项目面板模板
我们基本上在项目面板模板中包含项目模板和项目容器样式模板。尽管项目面板在可用模板列表中排在第三位,但它“某种程度上”是其他两个模板的父级,因为它定义了它们作为一个整体如何布局。这可以是 StackPanel
(默认)、WrapPanel
或 DockPanel
。基本上,任何继承自 Panel
类的东西都可以。您也可以指定 Grid
或 Canvas
,但意义不大,因为项目模板的每个实例只会相互堆叠……
恕我直言:项目面板模板是 ListBox
用于布局在项目模板中定义的生成项目的 Panel
。默认情况下,这是一个 StackPanel,但这可以根据您的数据和要求进行更改。
编辑项目面板模板最简单的理由是,将 StackPanel
的方向从 Vertical
更改为 Horizontal
。或者,可能将其设置为 WrapPanel
,但请注意,这可能会导致选择导航出现问题。(我正在等待一位朋友 (Jason Young) 博客他的解决方案,所以一旦有更新就会发布!)
项目模板
在这里,我们排列构成生成内容实例的不同元素。这可以是像 Icon
/Image
、Title
、伴随的 Description
、CheckBox
等……你可以想到的任何东西,都可能是可以在项目模板中布局的元素之一。
在我们的应用程序中,defwebserver 在一个水平 StackPanel
中设置了一个 Image
和一个 HyperlinkButton
。
这个例子可能是最基本的了,我们当然可以做得更多,这将在本文后面介绍。
项目容器样式模板
这无疑是三个可用模板中最有趣的一个,所有神奇的事情都发生在这里。因为在这里,我们通过与用户互动来制作具有视觉吸引力的动画和效果!
此模板的默认设置如上图所示。除了用于各种视觉状态的一些矩形外,我们还有一个 ContentPresenter
,它从项目模板获取输入。请注意,在“返回范围”图标旁边,此模板实际上称为“ListBoxItem 模板”,而在其上方的项目模板部分的屏幕截图中,在“返回范围”图标旁边。它实际上称为“ContentPresenter 模板”。忽略“SilverlightFileTemplate”,因为defwebserver在编辑原始模板的副本时创建了这个名称。所以你可以说前面图表中显示的模板排列应该更像下面的图表
无论您如何看待它,我们最可能对项目模板感兴趣,以布局我们的生成内容,以及项目容器样式模板来与此生成内容交互。我们使用视觉状态管理器 (VSM) 操作项目容器样式模板,如下图所示,我们拥有的状态组比以前处理按钮时多……
显而易见的补充是一个名为“LayoutStates
”的状态组,正如您所期望的,它可用于控制此模板中的元素在其 Loaded
和 Unloaded
状态期间。不那么明显的是 Blend 4 中添加的效果,它允许状态组中状态之间的一些有趣的过渡。
项目容器样式模板需要考虑的另一件事是,它有一个关联的样式应用于它,这与 ListBox 控件模板样式不同。
因此,一个 ListBoxItem
可以应用不同的样式,同时仍然使用相同的周围 ListBox
。所以,而不是拥有一个全新的 ListBox
,具有不同的生成内容交互、颜色和样式,可以只向 ListBox
传递一个新的 ListBoxItem
样式来改变交互、颜色和模板元素。
概述总结
这就是 ListBox
的三个附加模板的概述,如果您是第一次接触它们,可能会有点困惑。因此,最好的记忆方式是这些模板并不是真正的平等,您可能通过它们在附加模板列表中的排列而产生这种误解。它们基本上是相互嵌套的,但顺序与附加模板列表中显示的顺序相反。
基本上,沿着内容演示器,从 ListBox 控件模板中 ScrollViewer
的 ScrollContentPresenter
一直进入 Items Panel Template(也称为 ItemsPresenter Template)。然后,这将 dẫn 到 ItemContainerStyle
的内容演示器,它从 Item Template 获取其生成内容。因此,如果我们再次查看我们的图表,我们应该从中心向外看,以理解生成内容是如何呈现和样式化的。
此外,图中的紫色部分表示样式在 ListBox
控件中的放置位置。请再次理解,这是一个面向“设计师”的附加模板简化视图。
让我们开始吧!
为了开始编辑一些附加模板,我将从 defwebserver 的拖放文件管理器文章中接手,将其作为起点,通过附加模板格式化生成内容。
为了保持趣味性,因为我已经厌倦了它,并且为了释放更多“屏幕空间”,我再次改变了应用程序的外观。所以它有一个更薄的框架,折叠的铆钉(未移除),以及一个新的蓝色配色方案。
我还用几个铆钉样式化了 GridSplitter
,并将其与 PictureFrameControl
集成。那些眼尖的人会注意到我用新的扩展器和文件夹图标对 TreeView
进行了一些样式化。我这样做只是为了在我们处理 ListBox
时不分散应用程序的注意力。
所以从这里下载更新后的应用程序,我们就可以开始了!
项目面板模板
我们首先来看看这个模板,因为它是这三个模板中最不有趣的,而且在很多情况下可能根本不需要任何编辑。选择 ListBox
,然后选择 编辑附加模板 > 编辑项目布局 > 创建空模板。
将模板命名为“ListBoxItemsPanelTemplate
”,然后点击“确定”。
现在,如果我们查看对象和时间线,我们可以看到这是一个 ItemsPresenter 模板,正如我之前所说,这个模板控制/定义了控件模板中 ScrollContentPresenter
设置的区域的布局。
如上图所示,项目面板模板中只有一个 StackPanel
,其默认方向为 Vertical
。
所以选择 StackPanel
并将 HorizontalAlignment
从“Vertical
”更改为“Horizontal
”,如下图所示。
这应该会改变画板中的 ListBox
,以便在 ListBox
中只显示第一个生成的项目。其他生成的项目现在位于第一个项目的右侧,形成一个长流。这对于股票行情应用程序可能很棒,项目从右向左滚动,或从左向右滚动,但对于此应用程序来说并不合适。项目面板模板另一个非常酷的功能是能够将布局样式更改为 WrapPanel
。我在这里不会这样做,因为它需要更多的解释,如果您不确定 WrapPanel
的功能,请查看 Microsoft Mix10 的这个视频。
现在将 StackPanel
的 HorizontalAlignment
改回“Vertical
”,然后退出项目面板模板。
(借用巴布拉迪警官(南方公园)的话:“大家走吧,没什么可看的。”)
因为项目面板模板e 的内容差不多就是这样了!
项目模板
为了打破我在概述部分讨论模板的顺序。我们将在处理项目容器样式模板之前先查看项目模板。如果您一直专心致志并理解了我迄今为止关于模板的说法,您应该意识到,为了在项目容器样式模板中样式化生成内容,我们首先应该在项目模板中格式化生成内容。
defwebserver 在此应用程序中为我们提供了一些生成内容,但为了正确演示我们可以在项目模板中执行的操作,我希望有更多的示例数据可供使用,我已经在下载的项目中设置好了。
所以转到“数据”选项卡,选择“集合”,然后将其拖到画板中的 ListBox
上。
这应该会更改 ListBox
的示例数据,希望能与下图相同。
我们现在有了更多的生成内容,但目前它是一团糟。
所以选择 ListBox
并选择 编辑附加模板 > 编辑生成项目 > 编辑当前。
这将带我们进入项目模板,其中显示了 StackPanel
中的所有示例数据。
现在为了更清楚,按如下图所示重命名项目。
(示例数据已按其在数据选项卡中出现的相同顺序导入。)
我首先要做的就是将 StackPanel
的 Orientation
更改为 Horizontal
,并更改这些项目的整体布局,使它们从左到右堆叠。
在画板中,您现在应该会看到一个 CheckBox
,它的右侧有一个 Image
,图片的右侧有一些 Text
。
现在在对象和时间线中,将图像拖到 CheckBox
上方,以更改它们在 StackPanel
中显示的顺序。
在仍选中图像的情况下,将 Width
和 Height
都更改为 32,以缩小图像大小。
现在同时选择 ItemDescription
和 ItemTitle
元素,右键单击并选择 分组到 > StackPanel。
在“对象和时间线”中,将新的 StackPanel
拖到“购买”CheckBox
的上方,以更改父 StackPanel
的顺序。
展开子 StackPanel
,选择 ItemTitle
,并将其拖到 ItemDescription
元素上方,以更改此 StackPanel
的顺序。
选择 ItemTitle
上方的 StackPanel
,将其 Orientation
更改为 Vertical
,并仅在左侧设置 4 的 Margin
。
(确保 StackPanel
的 Width
和 Height
都设置为 Auto
)。
现在选择 ItemTitle
,将 Font
更改为粗体,大小更改为 7 pt。
所以我们现在有一个水平“父级”StackPanel
,元素从左到右排列。在这些水平元素的中间,我们有一个垂直 StackPanel
,其中一个元素排列在另一个元素的下方。希望您开始明白这个模板中发生了什么,并且已经注意到,当我们编辑顶部项目模板时,所有显示在下面的项目模板实例都会自动根据我们对项目模板的编辑进行更新。您还应该意识到 StackPanel
在布局方面有多么有用,我现在将做更多演示。我们仍然有三个元素在项目模板中不可见,因为它们位于包含 TitleDescription
文本的 StackPanel
的右侧,因此超出了屏幕。所以我们需要格式化 TitleDescription
文本,使其能够换行并占用更少的水平空间。但我也希望 ItemTitle
文本的长度不被打断,并流过(上方)所有其他后续元素(独立于 ItemDescription
文本)。
所以选择 ItemDescription
元素并选择 分组到 > StackPanel,并将 StackPanel
的 Orientation
设置为 Horizontal
。
再次选择 ItemDescription
,将字体大小更改为 7pt,并在高级属性中将 TextWrapping
更改为“Wrap
”。
现在将 ItemDescription
元素的 Width
更改为 140,并确保父 StackPanel
的 Width
设置为 Auto
。同时选择 Buy
、StockQuantity
和 StockTitle
元素,然后选择 分组到 > StackPanel。
确保 StackPanel
的 Orientation
设置为 Vertical
,并按 StockTitle
、StockQuantity
和 Buy
的顺序重新排列。
接下来,在对象和时间线中,将最新的 StackPanel
拖到其上方的 StackPanel
内部,使其直接位于 ItemDescription
下方,如下图所示。
(确保最新的 StackPanel
的 Width
和 Height
都设置为 Auto
,并且 Margin
都设置为 0)。
选择 StockTitle
元素,将字体大小改为 7 磅,并将文本设为粗体。现在将 StockQuantity
字体改为 7 磅,并将文本设为斜体。当应用程序运行时,结果应该如下图所示
(我已经将我的 ItemTitle
文本更改为 9 磅,以清楚地显示它流过并跨越其内部和下方的子 StackPanel
。)
希望我已经充分演示了项目模板,让您了解这个模板完全是关于布局的。以及项目模板中 StackPanel
的灵活性。显然,我们可以使用边距进一步分隔和格式化我们的项目,并将元素分组到网格中。但我会让您进一步探索……(编辑当前元素,添加更多元素,并根据您的需要格式化所有这些元素。)但是,我需要继续研究项目容器样式模板!
但在我们开始项目容器样式模板之前,我想放弃我们目前所做的所有更改。这些只是为了演示目的,而不是 defwebserver 和我正在开发的正在进行的应用程序的一部分。
所以重新加载原始的未编辑项目,再次进入 ListBox
的项目模板。
现在在资产中,找到我“快速”创建的“PageIcon
”,并将 PageIcon
的副本插入 StackPanel
中。
将 PageIcon
的 Width
设置为 14 像素,Height
设置为 16 像素。在对象和时间线中,将其重命名为“PageIcon
”,并将其拖到 StackPanel
列表的顶部,位于 Image
和 HyperlinkButton
的上方。
在画板中,我们现在应该有两个“页面”图标。
我创建的蓝色图标更适合我们的项目。此外,它还可以编辑,可以随我们的项目改变颜色。所以删除第二个白色 PageIcon
,因为它不再需要了。在剩余的 PageIcon
上,在Left
侧设置 4 的 Margin
,使其与 ListBox
的边缘保持距离。现在选择 HyperlinkButton
,并在Left
侧也设置 4 的 Margin
,使其与 PageIcon
保持距离。将 HyperlinkButton
的前景色更改为 Black
,使其与 TreeView
项目的文本颜色匹配。
(HyperlinkButton
可以通过其自身的模板和样式进行进一步编辑,如果需要的话。)
现在我们只需要在 ListBox
中的项目列表上方设置一些自由空间,所以选择 StackPanel
并在 Top
设置 9 的 Margin
。但是因为我们将此 Margin
应用于项目模板,所以此 Margin
应用于每个 Item
,将它们全部隔开。
我们不能在项目模板中仅为一个 Item
设置 Margin
,我们在这里所做的一切都将应用于每个项目。所以,相反,将顶部边距更改为 0,将底部边距更改为 1(为每个 Item
提供一点间距,并与 TreeView
项目间距匹配)。
现在转到 ListBox 控件模板,选择 [ItemsPresenter] 并将顶部边距设置为 8。
这应该会整体上拉开项目顶部的间距,而不是单个项目的间距。
项目容器样式模板
这就是我一直期待讨论的模板,部分原因是我把它留到了最后。但在我们进入这个模板更高级和有趣的部件之前,我们需要对鼠标悬停和选中状态进行一些基本格式化。
所以选择 ListBox
并选择 编辑附加模板 > 编辑生成项目容器 > 编辑当前。
(或者,如果您选择,则选择编辑副本模板)。
在对象和时间线中,选择 fillColor
元素。
现在进入 VSM,选择 MouseOver 状态并将元素 不透明度 更改为 100%。
在画板中,第一个项目现在应该有一个淡蓝色背景,如下图所示
返回到基本状态,然后选择 MouseOver 状态旁边的眼睛符号。
(这将允许我们编辑 fillColor
元素,而无需设置任何关键帧。)
将 fillColor
Rectangle
的 X 和 Y 半径都更改为 5,以使 Rectangle
的角变圆。将左边距和右边距更改为 3,将上边距更改为 1。现在运行应用程序,在 MouseOver 状态下,选中的项目应该如下图所示
回到 Blend,选择 MouseOver 状态并将元素 Opacity
设置回 35%。现在选择 fillColor2
元素,并在 Base 状态下,单击 Selected 状态旁边的眼睛符号。
正如我们之前所做的那样,将 fillColor2 Rectangle
的 X 和 Y 半径都更改为 5,并将左边距和右边距更改为 3,上边距更改为 1。对 FocusVisualElement
重复相同的过程,对角应用半径,并设置侧边距。
项目容器样式模板的疯狂应用
现在到了有趣的部分,为我们的 ListBox
应用一些夸张的“过度”效果。其中大部分显然不适用于实际应用程序,使用效果和动画时要记住,它们是为了增强您的应用程序,而不是分散对应用程序消息或目的的注意力!它们在前几次可能看起来很有趣和令人愉快,但这很快就会让用户感到沮丧和恼怒。所以不要得意忘形……
但是,我在这里会完全“过头”,只是为了演示可以完成什么!!!
我们先看看 MouseOver 状态,或者说是名为“CommonStates
”的状态组。我们在这里应用的任何效果都将应用于此状态组中的所有状态。
为 MouseOver 状态应用效果也将应用于 Normal 和 Disabled 状态。但与其讨论这些,不如让我们继续看看实际效果……
单击效果图标“fx”,然后选择涟漪。(或者您喜欢的任何其他效果!)
将效果持续时间设置为例如 1 秒,然后运行您的应用程序查看结果。
当我们将鼠标悬停在 ListBox
项目上时,会产生涟漪效果。当 ListBox
项目返回到其正常状态(鼠标移开)时,我们也会得到相同的效果。
自己尝试不同的效果,调整持续时间以适应,并尝试不同的缓动函数。
接下来,让我们看看 SelectionStates,特别是 Selected State。
选择一个您喜欢的特效,并设置该特效的持续时间。我选择了“从左到右滑入”,因为这在截图中很容易显示!
运行您的应用程序,并使用箭头键更改选定项目。
看看这如何影响选中状态和未选中状态。这可能不是您想要的,因为您可能不希望在未选中项上发生滑入。我们可以通过向选中状态添加过渡来控制这一点。
通过从选中状态 > 所有其他状态添加过渡,我们可以在取消选中项目时应用完全不同的效果。
所以为了演示,我为此过渡添加了一个新的“百叶窗”效果,持续时间为 1 秒。
现在,当我们取消选择一个项目(鼠标移开)时,而不是“滑入”效果,我们得到的是“百叶窗”效果,如下图所示
我们显然可以在所有状态组中这样做,因此效果可以根据您的确切需求进行定制。
(或者在过渡中完全没有效果,如果持续时间设置为 0)。
最后,在本节中,我想看看 ListBox
项目加载的 LayoutStates。
选择“BeforeLoaded”过渡,设置持续时间为 1 秒,缓动函数为“Bounce Out”。
现在,确保您已选择根网格,在变换部分,将 X 轴上的平移设置为 250。
现在运行应用程序,希望在加载过程中,ListBox
项目从右侧流入并从 ListBox
的左侧反弹。
(点击刷新或 F5 重新加载并再次显示动画。)
没有必要提供屏幕截图,所以如果您没有按照教程操作,请下载完成的项目!
就是这样
我的“过度”附加模板解释到此结束。回到defwebserver!请投票作废那些不敢留下评论说明我如何改进我的文章/教程的 3 星投票者!!!