ContentControl和静态资源

时间:2014-06-18 09:45:19

标签: xaml windows-phone-8

我尝试使用Windows Phone 8应用中的TextBlocks缺少CharacterEllipsis扩展我的应用。我在这里找到了一个很好的解决方案:http://nerdplusart.com/texttrimming-textblock-for-silverlight/

所以我在我的代码中实现了这个:

public class DynamicTextBlock : ContentControl
{
    #region Text (DependencyProperty)

    /// <summary>
    /// Gets or sets the Text DependencyProperty. This is the text that will be displayed.
    /// </summary>
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(DynamicTextBlock),
        new PropertyMetadata(null, new PropertyChangedCallback(OnTextChanged)));

    private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((DynamicTextBlock)d).OnTextChanged(e);
    }

    protected virtual void OnTextChanged(DependencyPropertyChangedEventArgs e)
    {
        this.InvalidateMeasure();
    }

    #endregion

    #region TextWrapping (DependencyProperty)

    /// <summary>
    /// Gets or sets the TextWrapping property. This corresponds to TextBlock.TextWrapping.
    /// </summary>
    public TextWrapping TextWrapping
    {
        get { return (TextWrapping)GetValue(TextWrappingProperty); }
        set { SetValue(TextWrappingProperty, value); }
    }
    public static readonly DependencyProperty TextWrappingProperty =
        DependencyProperty.Register("TextWrapping", typeof(TextWrapping), typeof(DynamicTextBlock),
        new PropertyMetadata(TextWrapping.NoWrap, new PropertyChangedCallback(OnTextWrappingChanged)));

    private static void OnTextWrappingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((DynamicTextBlock)d).OnTextWrappingChanged(e);
    }

    protected virtual void OnTextWrappingChanged(DependencyPropertyChangedEventArgs e)
    {
        this.textBlock.TextWrapping = (TextWrapping)e.NewValue;
        this.InvalidateMeasure();
    }

    #endregion

    #region LineHeight (DependencyProperty)

    /// <summary>
    /// Gets or sets the LineHeight property. This property corresponds to TextBlock.LineHeight;
    /// </summary>
    public double LineHeight
    {
        get { return (double)GetValue(LineHeightProperty); }
        set { SetValue(LineHeightProperty, value); }
    }

    public static readonly DependencyProperty LineHeightProperty =
        DependencyProperty.Register("LineHeight", typeof(double), typeof(DynamicTextBlock),
        new PropertyMetadata(0.0, new PropertyChangedCallback(OnLineHeightChanged)));

    private static void OnLineHeightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((DynamicTextBlock)d).OnLineHeightChanged(e);
    }

    protected virtual void OnLineHeightChanged(DependencyPropertyChangedEventArgs e)
    {
        textBlock.LineHeight = LineHeight;
        this.InvalidateMeasure();
    }

    #endregion

    #region LineStackingStrategy (DependencyProperty)

    /// <summary>
    /// Gets or sets the LineStackingStrategy DependencyProperty. This corresponds to TextBlock.LineStackingStrategy.
    /// </summary>
    public LineStackingStrategy LineStackingStrategy
    {
        get { return (LineStackingStrategy)GetValue(LineStackingStrategyProperty); }
        set { SetValue(LineStackingStrategyProperty, value); }
    }
    public static readonly DependencyProperty LineStackingStrategyProperty =
        DependencyProperty.Register("LineStackingStrategy", typeof(LineStackingStrategy), typeof(DynamicTextBlock),
        new PropertyMetadata(LineStackingStrategy.BlockLineHeight, new PropertyChangedCallback(OnLineStackingStrategyChanged)));

    private static void OnLineStackingStrategyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((DynamicTextBlock)d).OnLineStackingStrategyChanged(e);
    }

    protected virtual void OnLineStackingStrategyChanged(DependencyPropertyChangedEventArgs e)
    {
        this.textBlock.LineStackingStrategy = (LineStackingStrategy)e.NewValue;
        this.InvalidateMeasure();
    }

    #endregion

    /// <summary>
    /// A TextBlock that gets set as the control's content and is ultiately the control 
    /// that displays our text
    /// </summary>
    private TextBlock textBlock;

    /// <summary>
    /// Initializes a new instance of the DynamicTextBlock class
    /// </summary>
    public DynamicTextBlock()
    {
        // create our textBlock and initialize
        this.textBlock = new TextBlock();
        this.Content = this.textBlock;
    }

    /// <summary>
    /// Handles the measure part of the measure and arrange layout process. During this process
    /// we measure the textBlock that we've created as content with increasingly smaller amounts
    /// of text until we find text that fits.
    /// </summary>
    /// <param name="availableSize">the available size</param>
    /// <returns>the base implementation of Measure</returns>
    protected override Size MeasureOverride(Size availableSize)
    {
        // just to make the code easier to read
        bool wrapping = this.TextWrapping == TextWrapping.Wrap;

        Size unboundSize = wrapping ? new Size(availableSize.Width, double.PositiveInfinity) : new Size(double.PositiveInfinity, availableSize.Height);
        string reducedText = this.Text;

        // set the text and measure it to see if it fits without alteration
        this.textBlock.Text = reducedText;
        Size textSize = base.MeasureOverride(unboundSize);

        while (wrapping ? textSize.Height > availableSize.Height : textSize.Width > availableSize.Width)
        {
            int prevLength = reducedText.Length;
            reducedText = this.ReduceText(reducedText);

            if (reducedText.Length == prevLength)
            {
                break;
            }

            this.textBlock.Text = reducedText + "...";
            textSize = base.MeasureOverride(unboundSize);
        }

        return base.MeasureOverride(availableSize);
    }

    /// <summary>
    /// Reduces the length of the text. Derived classes can override this to use different techniques 
    /// for reducing the text length.
    /// </summary>
    /// <param name="text">the original text</param>
    /// <returns>the reduced length text</returns>
    protected virtual string ReduceText(string text)
    {
        return text.Substring(0, text.Length - 1);
    }

}

在我的XAML中,我使用这个:

<myNamespace:DynamicTextBlock Grid.Column="0" Text="Dies ist ein Text der sehr lang ist und umebrochen wird" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="-1,0,0,0" Foreground="{Binding IsHighlighted, Converter={StaticResource BoolToBrushConverter}}" FontSize="32" />

一切都很酷。现在我想对此应用Style。但以下方法不起作用:

Style="{StaticResource PhoneTextLargeStyle}" 

如何扩展解决方案以接受StaticRessource作为Style?

1 个答案:

答案 0 :(得分:0)

Windows Phone中的样式有TargetType,它们只能设置为该类型的控件或其子类型(子类)。 PhoneTextLargeStyle的目标是TextBlock,因此您无法将其置于其他控件上(例如DynamicTextBlock)。

您需要创建一个定位DynamicTextBlock的新样式并设置您喜欢的值。我想你可以找到PhoneTextLargeStyle风格的方式。