Windows应用程序确定是否修剪了TextBlock

时间:2014-08-29 23:29:46

标签: windows-8.1 windows-phone-8.1 windows-applications

我有一个具有固定高度/宽度的GridItem。

它包含一个设置了最大行的文本块。

如何判断此文字是否被修剪? 如果要修剪它,我想添加特殊功能。

2 个答案:

答案 0 :(得分:5)

旧方法 - 当TextWrapping设置为无

要知道是否修剪了TextBlock,我们可以订阅其SizeChanged事件并将其ActualWidth与您指定的MaxWidth进行比较。要获得ActualWidth正确 TextBlock,我们需要将TextTrimming保留为其默认值(即TextTrimming.None),然后设置一旦宽度超过就修剪它。

新方式 - 当TextWrapping设置为Wrap

现在我知道因为TextWrapping设置为Wrap并假设VirticalAlignment未指定(默认为Stretch),Width将会永远保持不变。我们只需要在SizeChanged的实际高度超过其父级高度时监控TextBlock事件。

让我们使用Behavior来封装上面的所有逻辑。这里需要提到的是,static辅助类具有一堆附加属性或从TextBlock继承的新控件可以完全相同;但作为一个大混合粉丝,我更愿意尽可能使用Behaviors

行为

public class TextBlockAutoTrimBehavior : DependencyObject, IBehavior
{
    public bool IsTrimmed
    {
        get { return (bool)GetValue(IsTrimmedProperty); }
        set { SetValue(IsTrimmedProperty, value); }
    }

    public static readonly DependencyProperty IsTrimmedProperty =
        DependencyProperty.Register("IsTrimmed", typeof(bool), typeof(TextBlockAutoTrimBehavior), new PropertyMetadata(false));

    public DependencyObject AssociatedObject { get; set; }

    public void Attach(DependencyObject associatedObject)
    {
        this.AssociatedObject = associatedObject;
        var textBlock = (TextBlock)this.AssociatedObject;

        // subscribe to the SizeChanged event so we will know when the Width of the TextBlock goes over the MaxWidth
        textBlock.SizeChanged += TextBlock_SizeChanged;
    }

    private void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        // ignore the first time height change
        if (e.PreviousSize.Height != 0)
        {
            var textBlock = (TextBlock)sender;

            // notify the IsTrimmed dp so your viewmodel property will be notified via data binding
            this.IsTrimmed = true;
            // unsubscribe the event as we don't need it anymore
            textBlock.SizeChanged -= TextBlock_SizeChanged;

            // then we trim the TextBlock
            textBlock.TextTrimming = TextTrimming.WordEllipsis;
        }
    }

    public void Detach()
    {
        var textBlock = (TextBlock)this.AssociatedObject;
        textBlock.SizeChanged += TextBlock_SizeChanged;
    }
}

XAML

<Grid HorizontalAlignment="Center" Height="73" VerticalAlignment="Center" Width="200" Background="#FFD2A6A6" Margin="628,329,538,366">
    <TextBlock x:Name="MyTextBlock" TextWrapping="Wrap" Text="test" FontSize="29.333">
        <Interactivity:Interaction.Behaviors>
            <local:TextBlockAutoTrimBehavior IsTrimmed="{Binding IsTrimmedInVm}" />
        </Interactivity:Interaction.Behaviors>
    </TextBlock>
</Grid>

请注意,Behavior公开了依赖项属性IsTrimmed,您可以将数据绑定到viewmodel中的属性(在这种情况下为IsTrimmedInVm)。

P.S。 WinRT中没有FormattedText函数,否则实现可能会略有不同。

答案 1 :(得分:1)

我们最终制作了一个静态函数

    // Ensure block does not have MAXLINES or text trimming set prior to checking
    public static bool IsTruncated(TextBlock block, int maxLines)
    {
        if (block == null)
        {
            throw new ArgumentNullException("block");
        }

        //the cut-off height is the height at which text will be cut off in the UI
        var cutOffHeight = maxLines * block.LineHeight;

        //determine whether the actual height of the TextBlock is greater than the cut-off height
        return block.ActualHeight > cutOffHeight;
    }

诀窍是确保在运行此功能之前未在Textblock上设置Maxlines和文本修剪。此函数返回后,即设置Maxlines时。在我的情况下,我只是将返回的布尔值保存在一个包含的对象中,所以我知道它更长。然后我设置maxlines和另一个按钮,以根据布尔值查看扩展内容。