web-dev-qa-db-fra.com

Accéder à un contrôle dans un ControlTemplate

Voici le 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>

Je vais essayer d'accéder au TextBlock nommé textBlock2.
J'ai essayé de remplacer OnApplyTemplate mais je suis devenu nul.

J'ai essayé:

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");

Le gridInTemplate est null (échantillon extrait de MSDN).
Les ct # sont tous nuls, bien sûr.

Qu'est-ce que j'oublie ici?

21
toy4fun

Si vous avez remplacé OnApplyTemplate, n'utilisez pas FindResource () ou Template.FindName () ni aucun piratage avec VisualTreeHelper. Utilisez simplement this.GetTemplateChild("textBlock2");

Les modèles dans WPF ont une étendue de noms autonome. En effet, les modèles sont réutilisés et aucun nom défini dans un modèle ne peut rester unique lorsque plusieurs instances d'un contrôle instancient chacune leur modèle. Appelez la méthode GetTemplateChild pour renvoyer des références aux objets provenant du modèle après son instanciation. Vous ne pouvez pas utiliser la méthode FrameworkElement.FindName pour rechercher des éléments à partir de modèles car FrameworkElement.FindName agit dans une portée plus générale et il n'y a pas de connexion entre la classe ControlTemplate elle-même et le modèle instancié une fois qu'il est appliqué.

Consultez ce lien:

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

Si votre exemple est un exemple Microsoft, je vous suggère de le relire. Vous avez peut-être sauté quelque chose.

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

Pour résumer - Utilisez GetTemplateChild () lors de la création d'un contrôle personnalisé, par exemple OnApplyTemplate et utilisez Template.FindName dans d'autres situations.

20
dev hedgehog

Essayez le code suivant. Cela renverra l'élément modèle.

this.GetTemplateChild("ControlName");
6
Ramesh

Votre code est correct, mais probablement pas au bon endroit ... FindName ne fonctionnera qu'après l'application du modèle. En règle générale, vous l'utilisez lorsque vous remplacez OnApplyTemplate dans un contrôle personnalisé. Étant donné que vous ne créez pas de contrôle personnalisé, vous pouvez le faire dans l'événement Loaded du bouton.

6
Thomas Levesque

vous pouvez utiliser VisualTreeHelper pour itérer l'arborescence visuelle du bouton pour obtenir n'importe quel enfant. Vous pouvez utiliser cette fonction générique de base pour l'obtenir

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);  
}

vous pouvez l'utiliser comme

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

Si vous pouvez obtenir le contrôle de la grille, essayez d'utiliser le code ci-dessous

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

La méthode "FrameworkElement.FindName (nom de chaîne)" utilise l'étendue de noms de la disposition où le bouton/contrôle est utilisé pour résoudre les noms. En bref, vous pouvez l'utiliser pour trouver des enfants dans une grille ou un panneau de pile dans la disposition de votre application. Mais vous ne pouvez pas utiliser la même chose pour trouver les enfants d'un contrôle que vous avez utilisé dans la mise en page de votre application (car les noms d'enfant modèles sont dans une portée différente)

Une façon d'obtenir les enfants dans votre situation est d'hériter du bouton. Puisque vous ne modifierez aucune autre propriété ou comportement du bouton, le nouveau bouton fonctionnera normalement. Pratiquement, je n'ai jamais utilisé une telle méthode pour accéder aux enfants modèles car je n'ai jamais eu besoin de les utiliser en dehors du cadre de la classe de contrôle.

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>
1
Karthik