2010-08-10 10 views
5

Je n'ai pas été en mesure de trouver une solution propre au problème suivant, même s'il y a déjà quelques questions connexes sur SO.Access Element à l'intérieur de Silverlight DataTemplate

Si j'ai un modèle de données qui est utilisé plusieurs fois, par exemple, un TreeViewItem.HeaderTemplate, comment puis-je modifier quelque chose le modèle pour seulement certains TreeViewItems.

Par exemple, disons que mon HeaderTemplate a une TVI textblock et en fonction de la chaîne, je veux faire le fontweight gras.

Je veux faire quelque chose comme ceci:

((TextBlock)myTreeView.Items.ElementAt(0).FindName("myTextBlock")).FontWeight = FontWeights.Bold; 

Quelqu'un at-il une solution pour cela? -> Merci Evan

Modifier: Est-il possible d'écrire une fonction générique pour obtenir un contrôle basé sur son nom même s'il se trouve dans un modèle de données?

LayoutRoot.FindName("myTextBlock"); fonctionnerait si myTextBlock était pas dans un DataTemplate. Comment puis-je écrire une fonction findElementInDataTemplate(string elementName, string parentName)?

La raison pour laquelle la réponse de Evan est pas ce que je suis à la recherche est parce que je développe un contrôle. Je veux que le développeur de l'application qui utilise mon contrôle puisse changer n'importe quel élément du contrôle. Si j'utilise la solution d'Evan, cela nécessiterait que le développeur de l'application ait accès à tous les modèles du contrôle. Possible, mais pas idéal. Merci!

+0

Si vous avez utilisé un DataTemplate qui contient un contrôle appelé « myTextBlock » plusieurs fois et ont une sorte de 'LayoutRoot.FindName ("myTextBlock") 'opération, lequel des nombreux contrôles appelés" myTextBlock "voudriez-vous que cette opération retourne? – AnthonyWJones

+0

@AnthonyWJones Bon point, modifié pour inclure un paramètre parentName. – NickHalden

+0

@AnthonyWJones: Normalement, deux contrôles avec nom ne sont pas possibles. Si vous conservez deux contrôles de même nom dans le modèle, le modèle est considéré comme incorrect. – Mahantesh

Répondre

0

quelle version de silverlight est-ce? Et quelle est l'année de "10 août à 18:55"?

dans la version actuelle de SL4 il ne semble pas être là ..

2

Si vous utilisez la liaison de données, avez-vous essayé d'utiliser un convertisseur de liaison? Dans ce cas, vous feriez quelque chose comme ...

FontWeight={Binding Path=TextProperty, Converter={StaticResource BoldConverter}} 

Et le convertisseur serait le long des lignes de ...

string myTestString = (string)value; 
if (myTestString.Contains("Bob")) 
    return FontWeights.Bold; 
return FontWeights.Normal; 

ce qui le rend moins douloureux pour essayer de racine à travers les éléments à localiser un particulier.

+0

Excellente solution à ma question. Maintenant, faisons comme si je posais la question que je voulais vraiment dire, vérifiez ma modification. – NickHalden

1

Ma première réaction à une telle exigence serait: êtes-vous vraiment sûr de vouloir faire cela? J'invite normalement les développeurs à regarder les modèles de contrôle existants utilisés. Dans ce cas, ce que vous semblez être un contrôle basé sur un modèle semble justifié.

Bien sûr, cela n'offre pas la flexibilité dont vous avez besoin. Ce que vous semblez être après, c'est le "Saint-Graal" des contrôles personnalisables, le désir de modifier les détails mineurs sur le contrôle sans avoir à dupliquer le modèle entier du contrôle. Bien sûr, ce n'est pas vraiment possible de manière déclarative, si je craignais la syntaxe et les règles sémantiques qui la régiraient.

Ceci dit, il y a toujours des exceptions. Donc, je vais présenter une option possible malgré le sentiment que vous ne devriez pas faire cela.

Cet ancien answer fournit une méthode d'extension Descendents qui vous permet d'énumérer les contrôles dans l'arborescence de l'objet. Étant donnée une instance d'un TreeViewItem vous devriez être en mesure de trouver le TextBlock que vous êtes après avec: -

TextBlock tb = treeViewItem.Descendents() 
       .OfType<TextBlock>() 
       .Where(t => t.Name == "myTextBlock") 
       .FirstOrDefault(); 
+0

Je reçois le message d'erreur IEnumerable dépendance objet ne contient pas une définition pour TypeOf – NickHalden

+0

@JGord: Assurez-vous que vous avez inclus 'using System.Linq' en haut de votre fichier de code. – AnthonyWJones

+0

Déjà eu cela là, d'autres pièges possibles? – NickHalden

4

Une façon que je l'ai accompli est de stocker tous les éléments nécessaires à une variable de collecte au niveau de la classe en utilisant les Loaded événement du contrôle.Prenez ce DataTemplate par exemple.

<DataTemplate> 
    ... 
    <TextBlock Loaded="TemplateTextBlock_Loaded" /> 
</DataTemplate> 

Ensuite, vous utilisez l'événement Loaded pour charger une sorte de collection pour une utilisation ultérieure. Bien sûr, si vous chargez et déchargez le contrôle, cela peut ne pas fonctionner correctement pour vous.

+0

Ça me fonctionne, AnthonyWJones a répondu utile quand l'arbre visuel a déjà été généré, mais celui-ci fonctionne avant ça aussi – hungryMind

0

peut aussi essayer

TextBlock txtBlk = grd.FindName ("txtBlkName") comme TextBlock;

où grd = élément racine (parent de l'élément que vous recherchez)