WPF自定义集合控件概述与遇到的问题

简介: WPF中涉及到控件,那么就不可能绕过Template。首先咱们来看一下WPF中基础集合控件ItemsControl涉及到的几个Template。 ItemsControl自身的Template,类型为ControlTemplate,其内部声明了一个ItemsPresenter用以呈现下述第2个Template。

WPF中涉及到控件,那么就不可能绕过Template。首先咱们来看一下WPF中基础集合控件ItemsControl涉及到的几个Template。

  1. ItemsControl自身的Template,类型为ControlTemplate,其内部声明了一个ItemsPresenter用以呈现下述第2个Template。当我们为集合控件赋予自定义模板时,ItemsPresenter不可丢弃,否则就失去了集合控件的意义;
  2. ItemsPanel,类型为ItemsPanelTemplate,其内容一般为可拥有多个子项的布局控件,如StackPanel、Grid等;
  3. ItemTemplate,类型为DataTemplate,呈现各数据项。

此时有人会问,数据项对应的类型是ControlTemplate的Template跑哪里去了?说的是呀,话说只要是继承自Control的控件都应该有这个Template属性,你看ItemsControl不就有吗。那么与各子项对应的这个属性应该怎么获取和设置呢。ItemsControl并没有提供给我们直接访问子项Template属性的方法,而是给了另一个属性ItemContainerStyle。ItemContainerStyle对应子项控件的Style,因此我们可以通过该Style设置子项控件的Template(上述第3条实际上对应子项控件Template内的ContentPresenter)。ItemContainerStyle对于ItemsControl是设置ContentPresenter的样式,不过ContentPresenter并没有Template属性,但是对于ListBox来说,它设置的是ListBoxItem的Style。

关于为什么wpf不给我们直接设置子项控件Template的方法,我没有特地研究过,不过我想微软的开发人员是这么想的:也许有人希望在保持原先默认的Template,对其它属性做一些掌控,比如可见性,那么何不如直接给你们设置所有样式的机会呢?(上帝说,要有光。于是就有了光。我等P民感恩戴德。)

WPF灵活地样式自定义给了开发人员极大的便利,同时也带来了可能破坏控件内在逻辑的问题。如何做到设计和逻辑分离,周大牛在WPF中自定义控件(3) CustomControl说的很详细,不过由于该博文“年代久远”,因此不排除有过时的内容。

原本我打算自定义一个名为UserAddDelItemsControl的集合控件,该控件继承自ItemsControl,为用户提供自增删子项的功能,但进行到一半的时候发现它的ItemsSource属性给我造成了相当大的麻烦。ItemsSource != null即有数据源绑定时,我要去判断可能的数据源类型,谢天谢地,大部分实体数据源都继承自IList,该接口有我期望的Insert、Remove等方法。但是假设我Insert一个新数据项(注意此处是数据项)的时候,我要不要去刷新界面,以及如何去刷新界面以反映后台数据列表的更改呢,所以我又要去判断数据源是否继承自INotifyCollectionChanged。假如它没有继承自INotifyCollectionChanged,那么我该怎么办?或许我该使用 ICollectionView.Refresh()方法?或许最终可以实现,但这样的控件并不能使我满意。我意识到要实现一个优良的可增删项的集合控件的真正重点和难点是需要重写ItemsSource属性,甚至要为其自定义一套数据源处理逻辑。水太深鸟!时间不多,我只能暂时放弃。

不过该项工作并没有白做,除自定义控件的知识外,重温并加深了关于Command、VisualState(4.0,可以理解为Trigger的升级版)的知识。

  1. RoutedCommand,可理解为事件event,或者更本质上,其实是一个信号。控件(如按钮)触发这个命令,有人(类或实例)收到这个命令,检查自己能否处理(拥有的CommandBindingCollection是否包含与这个命令相关的CommandBinding(检查其Command属性)),若找到对应的CommandBinding,那么就执行CommandBinding的Executed逻辑。
  2. 按第1条理解,RoutedCommand定义在哪里并不要紧,一般将之定义为自定义控件的静态字段。
  3. 事件和命令的区别,个人理解:事件的信号源是一个,关注者收到信号后做自己计划做的事,信号源并不care关注者做什么事;命令的信号源可以有多个,当然关注者也可以有多个,一般来说,所有信号源都期望关注者执行一个或一组逻辑,而关注者也遵循它们的意愿,这里的关注者可以理解为代理。
  4. 相同VisualStateGroup包含的所有VisualState互斥,使用VisualStateManager.GoToState来进行状态跳转。

转载请注明本文出处:http://www.cnblogs.com/newton/archive/2012/12/28/2836672.html

目录
相关文章
|
15天前
|
C# 开发者 Windows
基于Material Design风格开源、易用、强大的WPF UI控件库
基于Material Design风格开源、易用、强大的WPF UI控件库
|
4月前
|
C#
浅谈WPF之装饰器实现控件锚点
使用过visio的都知道,在绘制流程图时,当选择或鼠标移动到控件时,都会在控件的四周出现锚点,以便于修改大小,移动位置,或连接线等,那此功能是如何实现的呢?在WPF开发中,想要在控件四周实现锚点,可以通过装饰器来实现,今天通过一个简单的小例子,简述如何在WPF开发中,应用装饰器,仅供学习分享使用,如有不足之处,还请指正。
65 1
|
8月前
|
C# Windows
WPF技术之图形系列Polygon控件
WPF Polygon是Windows Presentation Foundation (WPF)框架中的一个标记元素,用于绘制多边形形状。它可以通过设置多个点的坐标来定义多边形的形状,可以绘制任意复杂度的多边形。
455 0
|
8月前
|
C# Windows
WPF技术之RichTextBox控件
WPF RichTextBox是Windows Presentation Foundation (WPF)中提供的一个强大的文本编辑控件,它可以显示富文本格式的文本,支持多种文本处理操作。
346 0
|
4月前
|
前端开发 C# 容器
浅谈WPF之控件拖拽与拖动
使用过office的visio软件画图的小伙伴都知道,画图软件分为两部分,左侧图形库,存放各种图标,右侧是一个画布,将左侧图形库的图标控件拖拽到右侧画布,就会生成一个新的控件,并且可以自由拖动。那如何在WPF程序中,实现类似的功能呢?今天就以一个简单的小例子,简述如何在WPF中实现控件的拖拽和拖动,仅供学习分享使用,如有不足之处,还请指正。
108 2
|
8月前
|
数据挖掘 数据处理 C#
WPF技术之DataGrid控件
WPF DataGrid是一种可以显示和编辑数据的界面控件。它可以作为表格形式展示数据,支持添加、删除、修改、排序和分组操作。
180 0
|
15天前
|
C# 开发者 C++
一套开源、强大且美观的WPF UI控件库
一套开源、强大且美观的WPF UI控件库
128 0
|
5月前
|
算法 C# UED
浅谈WPF之控件模板和数据模板
WPF不仅支持传统的Windows Forms编程的用户界面和用户体验设计,同时还推出了以模板为核心的新一代设计理念。在WPF中,通过引入模板,将数据和算法的“内容”和“形式”进行解耦。模板主要分为两大类:数据模板【Data Template】和控件模板【Control Template】。
95 8
|
8月前
|
定位技术 C# UED
WPF技术之ScrollViewer控件
WPF ScrollViewer是WPF中常用的一个控件,它提供了滚动视图的功能,可用于显示超出容器可视区域的内容。ScrollViewer通常用于容纳大量内容的控件,以在有限的空间内显示这些内容,并允许用户通过滚动来查看隐藏的部分。
699 0
|
8月前
|
前端开发 C#
WPF技术之ContentControl 控件
ContentControl 是 WPF 中的一个常见控件,用于显示单个内容元素。它可以包含任意类型的内容,包括文本、图像、控件等。
769 0