欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-04-03 11:06:18
wp7中textblock显示有文本数量限制。貌似超过2048个字符就不显示了。 从国外网站找了一个控件,实现加载大量文本显示,并且垂直滚动浏览。 实现原理其实挺简单的,就是动...

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

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

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

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

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

上代码:

[csharp]
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; 
        } 
 
    } 

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

这里抛砖引玉了。 


摘自 lanwilliam的专栏