wp7超大文本显示控件 垂直滚动

本文介绍了一种在 WP7 中实现长文本显示及滚动浏览的方法,通过创建 ScrollableTextBlock 控件来解决 TextBlock 显示文本数量受限的问题。该控件能够根据屏幕宽度动态拆分并显示大量文本,提升用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

wp7中textblock显示有文本数量限制。貌似超过2048个字符就不显示了。

从国外网站找了一个控件,实现加载大量文本显示,并且垂直滚动浏览。

实现原理其实挺简单的,就是动态创建多个textblock控件,每个控件显示部分内容。

有点,加载大量文本时,垂直方向滚动浏览,用户体验度较高(个人感觉比一页页翻页舒服多了)

缺点,由于加载了多个控件,所以加载速度慢(与文本长度有关),这也许时微软限制显示数量的原因。

上代码:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Text;

namespace wwb.Phone.Ctrls
{
    public class ScrollableTextBlock : Control
    {
        private StackPanel stackPanel;
        private TextBlock measureBlock;

        public ScrollableTextBlock()
        {
            // Get the style from generic.xaml
            this.DefaultStyleKey = typeof(ScrollableTextBlock);
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register(
                "Text",
                typeof(string),
                typeof(ScrollableTextBlock),
                new PropertyMetadata("ScrollableTextBlock", OnTextPropertyChanged));

        public string Text
        {
            get
            {
                return (string)GetValue(TextProperty);
            }
            set
            {
                SetValue(TextProperty, value);
            }
        }

        private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ScrollableTextBlock source = (ScrollableTextBlock)d;
            string value = (string)e.NewValue;
            source.ParseText(value);
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this.stackPanel = this.GetTemplateChild("StackPanel") as StackPanel;
            this.ParseText(this.Text);
        }


        private void ParseTextHide(string value)
        {
            if (this.stackPanel == null)
            {
                return;
            }
            // Clear previous TextBlocks
            this.stackPanel.Children.Clear();
            // Calculate max char count
            int maxTexCount = this.GetMaxTextSize();

            if (value.Length < maxTexCount)
            {
                TextBlock textBlock = this.GetTextBlock();
                textBlock.Text = value;
                this.stackPanel.Children.Add(textBlock);
            }
            else
            {
                int n = value.Length / maxTexCount;
                int start = 0;

                // Add textblocks
                for (int i = 0; i < n; i++)
                {
                    TextBlock textBlock = this.GetTextBlock();
                    textBlock.Text = value.Substring(start, maxTexCount);
                    this.stackPanel.Children.Add(textBlock);
                    start = maxTexCount;
                }

                // Pickup the leftover text
                if (value.Length % maxTexCount > 0)
                {
                    TextBlock textBlock = this.GetTextBlock();
                    textBlock.Text = value.Substring(maxTexCount * n, value.Length - maxTexCount * n);
                    this.stackPanel.Children.Add(textBlock);
                }
            }
        }

        private void ParseText(string value)
        {
            StringReader reader = new StringReader(value);

            if (this.stackPanel == null)
            {
                return;
            }
            // Clear previous TextBlocks
            this.stackPanel.Children.Clear();
            // Calculate max char count
            int maxTexCount = this.GetMaxTextSize();

            if (value.Length < maxTexCount)
            {
                TextBlock textBlock = this.GetTextBlock();
                textBlock.Text = value;
                this.stackPanel.Children.Add(textBlock);
            }
            else
            {                         
                string line = "";

                while (reader.Peek() > 0)
                {
                    line = reader.ReadLine();
                    ParseLine(line);                  
                }

            }

        }

        private void ParseLine(string line)
        {
            int lineCount = 0;
            int maxLineCount = GetMaxLineCount();
            string tempLine = line;
            StringBuilder sbLine = new StringBuilder();

            while (lineCount < maxLineCount)
            {
                int charactersFitted = MeasureString(tempLine, (int)this.Width);
                string leftSide = tempLine.Substring(0, charactersFitted);
                sbLine.Append(leftSide);
                tempLine = tempLine.Substring(charactersFitted, tempLine.Length - (charactersFitted));
                lineCount++;
            }

            TextBlock textBlock = this.GetTextBlock();
            textBlock.Text = sbLine.ToString();
            this.stackPanel.Children.Add(textBlock);

            if (tempLine.Length > 0)
            {
                ParseLine(tempLine);
            }           
        }

        private int MeasureString(string text, int desWidth)
        {
            
            int nWidth = 0;
            int charactersFitted = 0;

            StringBuilder sb = new StringBuilder();

            //get original size
            Size size = MeasureString(text);

            if (size.Width > desWidth)
            {
                string[] words = text.Split(' ');
                sb.Append(words[0]);

                for (int i = 1; i < words.Length; i++)
                {
                    sb.Append(" " + words[i]);
                    nWidth = (int)MeasureString(sb.ToString()).Width;

                    if (nWidth > desWidth)
                    {

                        sb.Remove(sb.Length - words[i].Length, words[i].Length);
                        break;
                    }
                }

                charactersFitted = sb.Length;
            }
            else
            {
                charactersFitted = text.Length;
            }

            return charactersFitted;
        }

        private Size MeasureString(string text)
        {
            if (this.measureBlock == null)
            {
                this.measureBlock = this.GetTextBlock();
            }

            this.measureBlock.Text = text;
            return new Size(measureBlock.ActualWidth, measureBlock.ActualHeight);
        }

        private int GetMaxTextSize()
        {
            // Get average char size
            Size size = this.MeasureText(" ");
            // Get number of char that fit in the line
            int charLineCount = (int)(this.Width / size.Width);
            // Get line count
            int lineCount = (int)(2048 / size.Height);

            return charLineCount * lineCount / 2;
        }

        private int GetMaxLineCount()
        {
            Size size = this.MeasureText(" ");
            // Get number of char that fit in the line
            int charLineCount = (int)(this.Width / size.Width);
            // Get line count
            int lineCount = (int)(2048 / size.Height) - 5;

            return lineCount;
        }

        private TextBlock GetTextBlock()
        {
            TextBlock textBlock = new TextBlock();
            textBlock.TextWrapping = TextWrapping.Wrap;
            textBlock.FontSize = this.FontSize;
            textBlock.FontFamily = this.FontFamily;
            // textBlock.FontStyle = this.FontStyle;
            textBlock.FontWeight = this.FontWeight;
            textBlock.Foreground = this.Foreground;
            textBlock.Margin = new Thickness(0, 0, MeasureText(" ").Width, 0);
            return textBlock;
        }

        private Size MeasureText(string value)
        {
            TextBlock textBlock = this.GetTextBlockOnly();
            textBlock.Text = value;
            return new Size(textBlock.ActualWidth, textBlock.ActualHeight);
        }

        private TextBlock GetTextBlockOnly()
        {
            TextBlock textBlock = new TextBlock();
            textBlock.TextWrapping = TextWrapping.Wrap;
            textBlock.FontSize = this.FontSize;
            textBlock.FontFamily = this.FontFamily;
            textBlock.FontWeight = this.FontWeight;
            return textBlock;
        }

    }
}

个人感觉,分页算法还是有改进空间的,尽可能减少控件数目,并且以后可以考虑实现动态加载,应该可以解决加载速度问题。

这里抛砖引玉了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值