Подтвердить что ты не робот

Доступ к элементу управления внутри ControlTemplate

Это xaml:

<Page.Resources>
    <ControlTemplate x:Key="WeddingButtonBigTemplate" TargetType="Button">
        <Grid>
            <Image x:Name="imgNormal" Source="../Images/Married_button2.png"/>
            <TextBlock x:Name="textBlock2" Style="{StaticResource RegularBlueSpecialBoldText}" LineHeight="28" LineStackingStrategy="BlockLineHeight" HorizontalAlignment="Center" Margin="10,30,10,70" TextWrapping="Wrap" TextAlignment="Center" VerticalAlignment="Stretch" >
                <Run FontSize="20" Text="The event of"></Run>
                <Run FontSize="28" Text="{DynamicResource strBride}"></Run>
            </TextBlock>
        </Grid>
    </ControlTemplate>
</Page.Resources>

<Grid HorizontalAlignment="Center" VerticalAlignment="Top" Width="1000">
    <Button x:Name="btnWedding" HorizontalAlignment="Left" Margin="10,20,0,-49" VerticalAlignment="Top" Template="{StaticResource WeddingButtonBigTemplate}" Foreground="#FF2B4072" Width="380" Click="btnClick" />
</Grid>

Я пытаюсь получить доступ к TextBlock с именем textBlock2.
Я попытался переопределить OnApplyTemplate, но получил значение null.

Я пробовал:

Grid gridInTemplate = (Grid)btnWedding.Template.FindName("grid", btnWedding);
var ct0 = btnWedding.Template.FindName("textBlock2", btnWedding);
var ct1 = btnWedding.FindName("textBlock2");
var ct2 = btnWedding.FindResource("textBlock2");

В таблице gridInTemplate указано значение NULL (выборка из MSDN).
Конечно, ct # являются нулевыми.

Что мне здесь не хватает?

4b9b3361

Ответ 1

Если вы переопределили OnApplyTemplate, не используйте FindResource() или Template.FindName() или любые хаки с помощью VisualTreeHelper. Просто используйте this.GetTemplateChild("textBlock2");

Шаблоны в WPF имеют автономный указатель имен. Это связано с тем, что шаблоны повторно используются, и любое имя, определенное в шаблоне, не может оставаться уникальным, когда несколько экземпляров элемента управления каждый экземпляр его шаблона. Вызовите метод GetTemplateChild для возврата ссылок на объекты, которые поступают из шаблона после его создания. Вы не можете использовать метод FrameworkElement.FindName для поиска элементов из шаблонов, потому что FrameworkElement.FindName действует в более общей области видимости, и нет никакого соединения между самим классом ControlTemplate и шаблоном-экземпляром после его применения.

Проверьте эту ссылку:

http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.gettemplatechild.aspx

Если ваш пример - пример microsoft, я предлагаю вам прочитать его снова. Возможно, вы что-то пропустили.

http://msdn.microsoft.com/en-us/library/bb613586.aspx

Подводя итог - используйте GetTemplateChild() при создании пользовательского элемента управления, например. OnApplyTemplate и используйте Template.FindName в других ситуациях.

Ответ 2

Ваш код верен, но, вероятно, не в нужном месте... FindName будет работать только после применения шаблона. Обычно вы используете его, когда вы переопределяете OnApplyTemplate в пользовательском элементе управления. Поскольку вы не создаете настраиваемый элемент управления, вы можете сделать это в событии Loaded кнопки.

Ответ 3

Попробуйте использовать следующий код. Это вернет шаблонный элемент.

this.GetTemplateChild("ControlName");

Ответ 4

вы можете использовать VisualTreeHelper для итерации визуального дерева кнопки для получения любого дочернего элемента. Вы можете использовать эту базовую общую функцию, чтобы получить ее

private static DependencyObject RecursiveVisualChildFinder<T>(DependencyObject rootObject)  
{  
    var child = VisualTreeHelper.GetChild(rootObject, 0);  
    if (child == null) return null;  

    return child.GetType() == typeof (T) ? child : RecursiveVisualChildFinder<T>(child);  
}

вы можете использовать его как

TextBlock textblock = RecursiveVisualChildFinder<TextBlock>(btnWedding);
if(textblock.Name == "textBlock2")
{// Do your stuff here
}

Ответ 5

Если вы можете получить управление сеткой, попробуйте использовать ниже код

TextBlock textBlock2 = (TextBlock)gridInTemplate.Children[1];

Ответ 6

В методе "FrameworkElement.FindName(имя строки)" используется указатель макета, где кнопка/элемент управления используется для разрешения имен. Короче говоря, вы можете использовать это, чтобы найти детей в панели сетки или стека в макете приложения. Но вы не можете использовать то же самое, чтобы найти дочерние элементы элемента управления, который вы использовали в макете приложения (поскольку имена шаблонов chidren находятся в другой области)

Один из способов заставить детей в вашей ситуации - наследовать кнопку. Поскольку вы не будете изменять какое-либо другое свойство или поведение кнопки, новая кнопка будет работать как обычная. Практически я никогда не использовал такой метод доступа к шаблонам, поскольку у меня никогда не было необходимости использовать их вне сферы контроля.

public class WeddingButton : Button
{
    public override void OnApplyTemplate()
    {
        TextBlock textBlock = this.GetTemplateChild("textBlock2") as TextBlock;
        base.OnApplyTemplate();
    }
}

<Page.Resources>
    <ControlTemplate x:Key="WeddingButtonBigTemplate" TargetType="Button">
        <Grid>
            <Image x:Name="imgNormal" Source="../Images/Married_button2.png"/>
            <TextBlock x:Name="textBlock2" Style="{StaticResource RegularBlueSpecialBoldText}" LineHeight="28" LineStackingStrategy="BlockLineHeight" HorizontalAlignment="Center" Margin="10,30,10,70" TextWrapping="Wrap" TextAlignment="Center" VerticalAlignment="Stretch" >
                <Run FontSize="20" Text="The event of"></Run>
                <Run FontSize="28" Text="{DynamicResource strBride}"></Run>
            </TextBlock>
        </Grid>
    </ControlTemplate>
</Page.Resources>

<Grid HorizontalAlignment="Center" VerticalAlignment="Top" Width="1000">
    <WeddingButton x:Name="btnWedding" HorizontalAlignment="Left" Margin="10,20,0,-49" VerticalAlignment="Top" Template="{StaticResource WeddingButtonBigTemplate}" Foreground="#FF2B4072" Width="380" Click="btnClick" />
</Grid>