我们都知道ItemsControl控件在WPF中的重要性,ItemsControl.ItemTemplate用的也非常多,那么其在模板应用中的角色是什么呢?要回答这个问题,我们先看其定义:
复制代码
public static readonly DependencyProperty ItemTemplateProperty =
DependencyProperty.Register(
"ItemTemplate",
typeof(DataTemplate),
typeof(ItemsControl),
new FrameworkPropertyMetadata(
(DataTemplate) null,
OnItemTemplateChanged));
/// <summary>
/// ItemTemplate is the template used to display each item.
/// </summary>public DataTemplate ItemTemplate
{
get { return (DataTemplate) GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
}
private static void OnItemTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((ItemsControl) d).OnItemTemplateChanged((DataTemplate) e.OldValue, (DataTemplate) e.NewValue);
}
protected virtual void OnItemTemplateChanged(DataTemplate oldItemTemplate, DataTemplate newItemTemplate)
{
CheckTemplateSource();
if (_itemContainerGenerator != null)
{
_itemContainerGenerator.Refresh();
}
}
复制代码
可以看到当ItemsControl.ItemTemplate改变时,会调用_itemContainerGenerator.Refresh()。这个方法的定义如下:
复制代码
// regenerate everything
internal void Refresh()
{
OnRefresh();
}
// Called when the items collection is refreshed
void OnRefresh()
{
((IItemContainerGenerator)this).RemoveAll();
// tell layout what happened
if (ItemsChanged != null)
{
GeneratorPosition position = new GeneratorPosition(0, 0);
ItemsChanged(this, new ItemsChangedEventArgs(NotifyCollectionChangedAction.Reset, position, 0, 0));
}
}
复制代码
可见这个方法调用OnRefresh(),后者的主要工作是清空已经生成的元素,并触发ItemsChanged事件,通知所有监听者列表已经被重置。
查找ItemsControl.ItemTemplate的引用会发现一个值得注意的方法ItemsControl.PrepareContainerForItemOverride:
复制代码
//ItemsControl****
/// <summary>
/// Prepare the element to display the item. This may involve
/// applying styles, setting bindings, etc.
/// </summary>
protected virtual void PrepareContainerForItemOverride(DependencyObject element, object item)
{
// Each type of "ItemContainer" element may require its own initialization.
// We use explicit polymorphism via internal methods for this.
//
// Another way would be to define an interface IGeneratedItemContainer with
// corresponding virtual "core" methods. Base classes (ContentControl,
// ItemsControl, ContentPresenter) would implement the interface
// and forward the work to subclasses via the "core" methods.
//
// While this is better from an OO point of view, and extends to
// 3rd-party elements used as containers, it exposes more public API.
// Management considers this undesirable, hence the following rather
// inelegant code.
www.shxjpco.com
HeaderedContentControl hcc;
ContentControl cc;
ContentPresenter cp;
ItemsControl ic;
HeaderedItemsControl hic;
www.shczh168.com
if ((hcc = element as HeaderedContentControl) != null)
{
hcc.PrepareHeaderedContentControl(item, ItemTemplate, ItemTemplateSelector, ItemStringFormat);
}
else if ((cc = element as ContentControl) != null)
{
cc.PrepareContentControl(item, ItemTemplate, ItemTemplateSelector, ItemStringFormat);
}
else if ((cp = element as ContentPresenter) != null)
{
cp.PrepareContentPresenter(item, ItemTemplate, ItemTemplateSelector, ItemStringFormat);
}
else if ((hic = element as HeaderedItemsControl) != null)
{
hic.PrepareHeaderedItemsControl(item, this);
}
else if ((ic = element as ItemsControl) != null)
{
if (ic != this)
{
ic.PrepareItemsControl(item, this);
}
}
}
复制代码
这个方法共两个参