开发者

Underline the implicit Textblock created in Silverlight for a ContentPresenter when Content is a string?

I am trying to create a template for a content control such as Button or HeaderedContentControl etc. where the text is underlined.

I just want to underline the text when Content="This text is underlined" is specified.

It must continue to work as normal if Content is another UIElement.

Most posts asking this same question are satisfied with modifying the template to only work for a string as content. Scott Gu has a good article about styling buttons but doesn't address this issue.

The following sample will work if you actually pass in Content as an instance of type TextBlock but not as a string. Surely the visual tree has a TextBlock so it should style it. Perhaps this 开发者_如何学Cis a Sivlerlight limitation.

This example shows black text and big red text when I want it to display both as big red text.

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


You could subclass whatever actual ContentControl (i.e. Button) you are using and override OnContentChanged in order to reset the Content property to an underlined TextBlock if the newContent is a string. In the case that the newContent is not a string it would perform in the usual way.

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

It's kind of annoying to subclass just to accomplish this but it avoids messy style templates and subclassing ContentPresenter.


Try this example, using a DataTemplate to custom-render string content (I've just set the background to red):

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

EDIT: just as a note, you could pull this out into a ContentControl style rather than applying it inline each time, if you need better reusability...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜