我已经和阿瓦隆尼亚和WPF斗争了一段时间了,我只是似乎不明白。具体来说,我没有模板。我不明白示例化模板的“级别”,以及如何知道哪些模板可用。这个WPF对我来说根本不是“可发现的”(借用UI/UX短语)。
例如,在这个SO帖子中:How can you add Children to an ItemsPanelTemplate of an ItemsControl in WPF?
显示了三种不同类型的模板:
ItemsControl
→ItemsControl.ItemsPanel
→ItemsPanelTemplate
ItemsControl
→ItemTemplate
→DataTemplate
ItemsControl
→Template
→ControlTemplate
当试图为一些自定义数据结构提供图形表示时,我怎么知道要使用哪个模板?这一切对我来说似乎都是临时的,我还没有能够弄清楚底层的规则或模式来猜测模板何时可用,以及如何调用它,而不必去某处寻找一个示例。
我错过了什么?有人能解释一下大局吗,或者告诉我在哪里我可以变得更开明?
1条答案
按热度按时间lf3rwulv1#
Long Story Short(TL; DR)
当试图为一些自定义数据结构提供图形表示时,我怎么知道要使用哪个模板?
您将为您的数据类型创建数据模板。主要区别在于:
ControlTemplate
,它被分配给Control
的Template
属性。DataTemplate
,它被分配给ContentControl
(单个项目)或ItemsControl
(多个项目)的ItemTemplate
属性。有一个特殊的HierarchicalDataTemplate
用于TreeView
中使用的子项数据类型。ItemsControl
的Panel
,则使用项目面板模板。它的类型是ItemsPanelTemplate
,它被分配给ItemsControl
的ItemsPanel
属性。短篇小说
误解
我没有模板。我不明白示例化模板的“级别”,以及如何知道哪些模板可用。
我认为你的思维模式误导了你。有不同类型的模板服务于不同的 * 目的 *,而不是 * 级别 *。这些模板类型既不是层次结构的一部分(在层次结构中,一个模板类型取代另一个模板类型),也不是可互换的。
控制模板
用途
在下文中,我们所说的控制是指基类型
Control
或直接或间接从它派生的类型,如Button
,ComboBox
或TextBlock
。让我们以Button
为例来看看控件是如何设计的。一个按钮有不同的状态,如 * 鼠标悬停 * 或 * 按下 *,可以单击以执行操作。这些状态被实现为属性IsMouseOver
和IsPressed
,点击它的信号被暴露为Click
事件等等。现在你有了一个功能齐全的按钮,但没有图形界面可以交互。这就是控制模板发挥作用的地方。它们定义控件的视觉表示和行为。请注意单词 visual,因为这是模板的关键点,将任何控件的逻辑或核心与其显示方式分离。我们所说的视觉行为是指用户在与控件交互时所体验到的。您可以决定当鼠标悬停在按钮上时,按钮会改变颜色,或者可以 Flink 它。这也是以各种方式指定的控件模板的一部分,包括动画,triggers或visual states。
但是为什么呢?在过去,UI框架通常是完全用代码编写的,例如. C++,不使用XAML等标记语言。控件是使用绘图基元或逐像素在代码中绘制的。视觉,行为和逻辑被烘焙成一个类型。为了适应视觉效果或交互,您必须派生自定义控件并自己绘制,或者从头开始编写控件。这是麻烦的并且损害可维护性以及灵活性。
外表是主观的
更改控件的视觉表示或行为的原因有很多:
您现在可以在XAML中为每个案例简单定义一个控制模板,而不是为每个案例派生一个新按钮。您仍然有一个按钮类型,因为它的实现从未改变。
定义及用法
ControlTemplate
通常在Style
中的XAML中定义,直接分配给控件的Template
属性或放入资源字典并在需要时引用,但它也可以内置在代码中。总结
控件模板有助于将控件的逻辑或核心与其可视表示形式和行为分开。WPF为内置类型提供样式和控件模板。如果要更改任何控件的视觉外观或行为,请为其编写自定义控件模板。
为您指引
如果您创作自定义控件或主题,或者如果您想要自定义控件的视觉树(包括更改视觉外观或行为),请为控件创建控件模板。每个内置的WPF控件都有一个默认的样式和控件模板,描述为here。
资源
数据模板
用途
顾名思义,DataTemplate是数据的模板。数据是您定义的任何携带信息的结构,例如一个
Person
类,带有名字和出生日期,甚至可能是一个图像。现在,我们面临着与控制相同的问题:如何直观地表示这些数据?我们要将UI控件烘焙到数据模型中吗?不,我们希望将我们的数据与它的显示方式解耦,因为这些是完全独立的关注点。外表又是主观的
同样,您没有将数据复制、派生和耦合到视图,而是使用单个数据类型和多个数据模板,每个模板都针对特定的信息需求和场景进行定制。
定义及用法
DataTemplate
通常在XAML中定义,并分配给ContentControl
(单个项目)的ContentTemplate
属性或ItemsControl
(多个项目)的ItemTemplate
属性,或者放在资源字典中并在需要时引用。你也可以在代码中定义它。在数据模板中,可以使用bindings引用数据。请注意,您的数据类型需要为implement the
INotifyPropertyChanged
interface,否则当属性更改时,绑定将不会得到通知。对于集合属性,使用OberservableCollection<T>
,否则通过例如添加或删除项也不会通知绑定。分层的特殊情况
数据可以是分层的,比如员工是部门的一部分,部门是公司的一部分。对于这种情况,有一个特殊的类型
HierarchicalDataTemplate
。它用于TreeView
控件。它与常规数据模板相同,不同之处在于它允许您通过其ItemsSource
属性指定子项源,并通过其ItemTemplate
属性指定子数据模板。可以将其想象为嵌套多个项控件,但要通过模板来实现。这允许单独显示同质和异质的数据层次结构。避免的做法
数据模板用于数据,控件模板用于控件。从技术上讲,你可以编写一个控制模板而不是数据模板,没有什么可以阻止你这样做,甚至是WPF开发人员绝望的尖叫声从他们的眼睛流血。永远不要这样做。说出来
总结
数据模板将数据与其可视化表示分开。
为您指引
当试图为一些自定义数据结构提供图形表示时,我怎么知道要使用哪个模板?
这就是你的案子每当您使用或创建需要在用户界面中自定义外观或行为的数据类型时,请创建数据模板。如果您想在多个地方重用它,请将其放入资源字典中,并将其包含在应用程序资源中,或在需要的地方将其包含在本地。如果没有定义数据模板,WPF将默认显示
ToString
方法的结果。更复杂场景
如果您遇到了一个案例,您希望为您的数据创建一个复杂的控件,例如:
Person
的输入掩码需要自定义逻辑,不能仅用模板表示,请考虑创建UserControl
或custom control from scratch。资源
项目面板模板
用途
ItemsPanelTemplate
是一种非常特殊的模板类型,仅适用于ItemsControl
。它用于更改其Panel
。面板控制项控件中的项的排列、大小调整和最终呈现方式。WPF提供多个面板用于托管项目,例如:
Canvas
DockPanel
Grid
StackPanel
WrapPanel
每个面板都以不同的方式显示项目。
StackPanel
可以垂直或水平地放置一个接一个的项目。WrapPanel
将它们放在一行中,如果没有足够的水平空间,则溢出到下一行。Grid
允许您定义表格布局。请注意,某些控件默认为use a virtualizing panel,以提高性能。WPF中的大多数面板都没有虚拟化,在这些情况下可能会导致问题。
连布局都是主观的
默认情况下,标准
ListBox
将垂直堆叠项目。这并非在所有情况下都是可取的。也许你想像WrapPanel
一样,在溢出的情况下显示它们。为了改变这一点,您必须派生ListBox
和重写方法来创建您自己的自定义方法,尽管除了布局之外没有什么真正的变化。这在多个方面都是不好的,这就是为什么所有的ItemControl
都提供了一种在不改变控件本身的情况下交换项目面板的方法。定义及用法
ItemsPanelTemplate
通常在XAML中的Style中定义,直接分配给ItemsControl
的ItemsPanel
属性或放入资源字典并在需要时引用。它也可以在代码中定义。总结
项目面板模板用于更改
ItemsControl
的Panel
。为您指引
创建一个自定义的
ItemsPanelTemplate
,如果你想通过使用合适的Panel
来改变ItemsControl
中显示的项目的排列,例如:其中一个内置面板。资源