如何在DataTemplate中找到应用于ContentPresenter的元素?

时间:2011-12-22 18:36:50

标签: c# wpf

我为用户创建了一个AddressInput控件来输入地址。根据它的使用位置,控件将具有不同的外观,因此我提供了一个名为AddressTemplate的DataTemplate属性。

默认样式如下所示:

<Style TargetType="{x:Type addressUI:AddressInput}">
    <Setter Property="AddressTemplate"
            Value="{StaticResource DefaultAddressTemplate}" />

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type addressUI:AddressInput}">
                <GroupBox Header="Address">
                    <ContentPresenter ContentTemplate="{Binding Path=AddressTemplate, RelativeSource={RelativeSource TemplatedParent}}"
                                      Content="{Binding Path=Address, RelativeSource={RelativeSource TemplatedParent}}"
                                      x:Name="PART_AddressPresenter" />
                </GroupBox>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我的所有地址数据模板都将包含一个用于选择国家/地区的组合框(名为“PART_CountriesList”)。我需要在选择更改时触发一些代码隐藏操作,这意味着我需要挂钩SelectionChanged事件。在我的AddressInput中,我需要在AddressTemplate中找到PART_CountriesList。

我可以像这样得到“PART_AddressPresenter”ContentPresenter:

public override void OnApplyTemplate()
{
    base.OnApplyTemplate();

    var addressPresenter = Template.FindName("PART_AddressPresenter", this) as ContentPresenter;
}

现在如何在AddressTemplate中包含“PART_CountriesList”?

我试过了:

var countriesList = AddressTemplate.FindName(“PART_CountriesList”,addressPresenter);

抛出异常是因为addressPresenter尚未应用其模板。我知道ContentPresenter具有OnApplyTemplate覆盖,但为此用途扩展它似乎很愚蠢。

我想如果我要扩展ContentPresenter,我会创建一个新的可重用版本,只要OnApplyTemplate方法执行就会触发事件。这可能会解决我的问题,但似乎很疯狂。还有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

我很好奇是否有人有“正确”的方式来做这件事,但是使用FindName我总是诉诸于这样的事情:

Dispatcher.BeginInvoke( new Action(() =>
{
    // Call FindName here
}), System.Windows.Threading.DispatcherPriority.Render );

这可能会导致闪烁,因为你要等到数据模板化完成并渲染后才能运行你的代码,所以如果你要做的事情会影响控件的外观,这并不总是很好选项。