<Style TargetType="{x:Type local:CustomItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter x:Name="PART_Presenter"/>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel x:Name="PART_StackPanel" IsItemsHost="True"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
尝试访问StackPanel以在更改子项时设置事件。
[TemplatePartAttribute(Name = "PART_StackPanel", Type = typeof(StackPanel))]
[TemplatePartAttribute(Name = "PART_Presenter", Type = typeof(ItemsPresenter))]
public class CustomItemsControl: ItemsControl
{
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var presenter = (ItemsPresenter)this.Template.FindName("PART_Presenter", this);
var stackPanel = (StackPanel)this.ItemsPanel.FindName("PART_StackPanel",this);
}
}
当我尝试找到StackPanel时,获取异常。
InvalidOperationException:
此操作仅对已应用此模板的元素有效。
请告知是否有办法在ItemsPanelTemplate中找到TemplatePart。我什么时候应该知道什么时候应用ItemsPanelTemplate?
答案 0 :(得分:5)
另一种选择是在ItemControl的.ApplyTemplate()
方法中调用ItemsPresenter上的OnApplyTemplate
。然后,对.FindName
的调用将成功。
[TemplatePartAttribute(Name = "PART_StackPanel", Type = typeof(StackPanel))]
[TemplatePartAttribute(Name = "PART_Presenter", Type = typeof(ItemsPresenter))]
public class CustomItemsControl : ItemsControl
{
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var presenter = (ItemsPresenter)this.Template.FindName("PART_Presenter", this);
presenter.ApplyTemplate();
var stackPanel = (StackPanel)this.ItemsPanel.FindName("PART_StackPanel", presenter);
}
}
答案 1 :(得分:1)
想出Loaded事件是在ItemsPanelTemplate上等待的事件。我能够使用TemplatePart名称找到StackPanel。感谢Rick建议在Presenter中找到StackPanel。
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
this.Loaded += new Accordion_Loaded;
}
void Accordion_Loaded(object sender, RoutedEventArgs e)
{
var presenter = (ItemsPresenter)this.Template.FindName("PART_Presenter", this);
var stackPanel = (StackPanel)this.ItemsPanel.FindName("PART_StackPanel", presenter);
}
答案 2 :(得分:0)
FindName
方法仅在已展开的模板中查找名称,并ItemsPanel
展开ItemsPresenter
,而不是ItemsControl
。在您的情况下,"PART_StackPanel"
将永远是"PART_Presenter"
的孩子,因此您可以像这样获得对它的引用:
var stackPanel = (StackPanel)VisualTreeHelper.GetChild(presenter, 0);