2010-08-11 15 views
1

J'essaye de créer un modèle pour un contrôle de contenu tel que Button ou HeaderedContentControl etc. où le texte est souligné.Souligner le bloc de texte implicite créé dans Silverlight pour un ContentPresenter lorsque Content est une chaîne?

Je veux juste souligner le texte lorsque Content="This text is underlined" est spécifié.

Il doit continuer à fonctionner normalement si Content est un autre UIElement.

La plupart des articles posant cette même question se contentent de modifier le modèle pour qu'il ne fonctionne que pour une chaîne en tant que contenu. Scott Gu a un bon article sur styling buttons mais ne résout pas ce problème.

L'exemple suivant fonctionnera si vous transmettez réellement Content en tant qu'instance de type TextBlock mais pas en tant que chaîne. Sûrement l'arbre visuel a un TextBlock donc il devrait le styler. Peut-être que c'est une limitation de Sivlerlight.

Cet exemple affiche du texte en noir et un gros texte rouge lorsque je souhaite qu'il s'affiche à la fois en tant que gros texte en rouge.

<navigation:Page.Resources> 
    <Style TargetType="TextBlock" x:Key="style123"> 
     <Setter Property="Foreground" Value="Red"/> 
     <Setter Property="FontSize" Value="72"/> 
     <Setter Property="FontWeight" Value="Bold"/> 
     <Setter Property="TextDecorations" Value="Underline"/> 
    </Style> 
</navigation:Page.Resources> 

<StackPanel>   

    <!-- This doesn't work and shows black text --> 
    <ContentPresenter Content="Small black text"> 
     <ContentPresenter.Resources> 
      <Style TargetType="TextBlock" BasedOn="{StaticResource style123}"/> 
     </ContentPresenter.Resources> 
    </ContentPresenter> 

    <!-- This works and shows red text --> 
    <ContentPresenter> 
     <ContentPresenter.Content> 
      <TextBlock Text="This is big red text"/> 
     </ContentPresenter.Content> 

     <ContentPresenter.Resources> 
      <Style TargetType="TextBlock" BasedOn="{StaticResource style123}"/> 
     </ContentPresenter.Resources> 
    </ContentPresenter> 

</StackPanel> 
+0

PS. Je vais bien si la solution est quelque chose de fou comme le sous-classement ContentPresenter et l'interception d'événements ou quelque chose comme ça. hmm je viens de réaliser peut-être que cela pourrait fonctionner ... –

+0

Des solutions folles sont rarement nécessaires dans WPF - voir ma réponse ;-) –

Répondre

1

Vous pouvez sous-classe réelle quelle que soit ContentControl (à savoir Button) que vous utilisez et passer outre OnContentChanged afin de réinitialiser la propriété à un ContentTextBlock si la newContent soulignée est une chaîne. Dans le cas où le newContent n'est pas une chaîne, il fonctionnera de la manière habituelle.

public class UnderlineButton : Button 
{ 
    protected override void OnContentChanged(object oldContent, object newContent) 
    { 
     if (newContent is string) 
     { 
      TextBlock textBlock = new TextBlock(); 
      textBlock.Text = newContent as string; 
      textBlock.TextDecorations = TextDecorations.Underline; 
      this.Content = textBlock; 
     } 

     base.OnContentChanged(oldContent, newContent); 
    } 
} 

Il est un peu ennuyeux de sous-classe juste pour y arriver, mais il évite les modèles de style en désordre et subclassing ContentPresenter.

+0

merci! cela ne devrait-il pas être une autre condition pour base.OCC()? –

+0

Je ne pense pas, vous aurez toujours envie de notifier le contrôle de base du changement de contenu. Dans le cas où le nouveau contenu est une chaîne, vous êtes simplement en train de "sauter" et de changer le contenu en premier. –

+0

ahh c'est vrai ... c'est OnContentChanged par opposition à OnContentChanging (qui ne peut pas réellement quitter - je n'ai pas vérifié). ressembler à cette solution est le meilleur pour Silverlight dès maintenant! –

0

Essayez cet exemple, en utilisant un DataTemplate au contenu sur mesure de rendre string (je viens comme arrière-plan rouge):

<ContentControl Content="{Binding YourData}" > 
    <ContentControl.Resources> 
    <DataTemplate DataType="{x:Type s:String}"> 
     <TextBlock Text="{Binding}" Background="Red" /> 
    </DataTemplate> 
    </ContentControl.Resources> 
</ContentControl> 

EDIT: comme une note, vous pourriez tirer ceci dans un ContentControl style plutôt que de l'appliquer en ligne à chaque fois, si vous avez besoin d'une meilleure réutilisabilité ...

+0

J'ai essayé d'obtenir quelque chose comme ça avant de travailler avec Silverlight. Je sais que c'est WPF cos dans Silverlight, nous n'avons même pas de fond sur un TextBlock! :-( –

+0

Alors, vous l'avez finalement réussi? Quelle était votre solution? –