Windows Phone 文本表情显示控件

现在要将  “我真是[哭][笑]不得"   类似格式的文本显示成表情图片和文字的混排。像新浪微博或qq。

在wp的列表中。 那么其实主要工作就是解析字符串中[xx]这种格式的字符。然后以图片显示出来。

1.解析表情字符串

解析表情字符串。主要就是括号匹配+匹配出来的[xx]是不是我们的表情。

主要思路 建立2个字节数组,一个是储存可能是表情的字符串,另一个是储存不是表情的普通文本

 遍历这个表情字符串。如果遇到”[“就存到表情数组。如果遇到”]“就来验证夹在括号中的文本

是不是我们需要的表情。

2.建立一个内容列表

建立一个内容列表,这个列表里将上个步骤区分开的文本内容和表情内容装在内容列表中。用来后

续显示在控件中

3.在控件中显示文本和表情

这里用的控件是RichTextBox。RichTextBox的Blocks中可以添加段落。而段落里面可以添加文本

和图片等。

这里附上代码--!

FaceTextBlock.cs

namespace Controls.HcControl
{
    [TemplatePart(Name = FaceTextBlockCanvasName, Type = typeof(Canvas))]
    public class FaceTextBlock : Control
    {
        #region XXX

        /// <summary>
        /// ContentControl的xaml样式
        /// </summary>
        private static string TemplateString
        {
            get
            {
                return
                "<ControlTemplate " +
                    "xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" " +
                    "xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">" +
                    "<RichTextBox x:Name=\"FaceTextBlockCanvas\" Background=\"{TemplateBinding Background}\" Foreground=\"{TemplateBinding Foreground}\" VerticalContentAlignment=\"Top\" HorizontalContentAlignment=\"Left\">" +

                    "</RichTextBox>" +
                "</ControlTemplate>";
            }
        }

        /// <summary>
        /// 表情图片路径
        /// </summary>
        private const string FacesPath = @"/Controls;component/Images/Face/{0}.png";

        /// <summary>
        /// 表情内容数组
        /// </summary>
        private string[] FacesStr = { "[鄙视]", "[不高兴]", "[吃惊]", "[汗]", "[呵呵]" +
                                      "[挤眼]", "[囧]", "[可爱]", "[可怜]", "[困]" +
                                      "[泪]", "[怒]", "[衰]", "[嘻嘻]", "[右哼哼]", "[左哼哼]"};

        #endregion

        #region Constants

        private const string FaceTextBlockCanvasName = "FaceTextBlockCanvas";

        #endregion

        #region Member

        /// <summary>
        /// 表情和文本的画布
        /// </summary>
        private RichTextBox _richTextBox;

        /// <summary>
        /// 文本表情内容容器
        /// </summary>
        private List<HcBaseTBContent> _contentList = new List<HcBaseTBContent>();
        #endregion

        #region LiseCycle

        public FaceTextBlock()
        {
            Template = (ControlTemplate)XamlReader.Load(TemplateString);

            this.Loaded += new RoutedEventHandler(FaceTextBlock_Loaded);
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            _richTextBox = GetTemplateChild(FaceTextBlockCanvasName) as RichTextBox;
        }

        void FaceTextBlock_Loaded(object sender, RoutedEventArgs e)
        {
            OnTextChanged();
        }

        #endregion

        #region Methods

        /// <summary>
        /// 绘制文本头像啥的。
        /// </summary>
        private void OnTextChanged()
        {
            _contentList.Clear();

            //解析表情字符串
            AnalyzeText();

            //绘制UI
            DrawTextUI();
        }

        /// <summary>
        /// 解析表情字符串
        /// </summary>
        private void AnalyzeText()
        {
            //表情栈
            List<Char> faceStack = new List<Char>();
            //文本栈
            List<Char> textStack = new List<Char>();
            //是否进入表情栈标志
            bool isPushFace = false;

            if (!String.IsNullOrWhiteSpace(Text))
            {
                Char[] chars = Text.ToCharArray();

                for (int i = 0; i < chars.Length; i++)
                {
                    #region 入栈选择判断
                    if (chars[i] == '[')
                    {
                        isPushFace = true;
                    }
                    if (chars[i] == ']')
                    {
                        isPushFace = false;
                    }
                    #endregion

                    #region 字符入栈规则
                    if (isPushFace)
                    {
                        if (faceStack.Count >= 1 && faceStack.First() == '[' && chars[i] == '[')
                        {
                            textStack.AddRange(faceStack);
                            faceStack.Clear();
                        }

                        if (faceStack.Count <= 0 || faceStack.First() == '[')
                        {
                            faceStack.Add(chars[i]);
                        }
                    }
                    else
                    {
                        if (faceStack.Count >= 2 && faceStack.First() == '[' && chars[i] == ']')
                        {
                            faceStack.Add(chars[i]);
                        }
                        else
                        {
                            textStack.Add(chars[i]);
                        }
                    }
                    #endregion

                    #region 字符填充内容
                    if (faceStack.Count > 2 && faceStack.Last() == ']')
                    {
                        StringBuilder faceStr = new StringBuilder();
                        StringBuilder textStr = new StringBuilder();

                        faceStr.Append(faceStack.ToArray());
                        textStr.Append(textStack.ToArray());

                        if (FacesStr.Contains(faceStr.ToString()))
                        {
                            //_contentList.Add(new HcTextTBContent(textStr.ToString(), this));
                            foreach (var item in textStack)
                            {
                                _contentList.Add(new HcTextTBContent(item.ToString(), this));
                            }
                            _contentList.Add(new HcFaceTBContent(faceStr.ToString(), this));
                        }
                        else
                        {
                            //textStr.Append(faceStr);
                            //_contentList.Add(new HcTextTBContent(textStr.ToString(), this));

                            textStack.AddRange(faceStack);
                            foreach (var item in textStack)
                            {
                                _contentList.Add(new HcTextTBContent(item.ToString(), this));
                            }
                        }

                        faceStack.Clear();
                        textStack.Clear();
                    }
                    else
                    {
                        if (chars.Count() == i + 1)
                        {
                            //StringBuilder textStr = new StringBuilder();
                            //textStr.Append(textStack.ToArray());
                            //_contentList.Add(new HcTextTBContent(textStr.ToString(), this));
                            foreach (var item in textStack)
                            {
                                _contentList.Add(new HcTextTBContent(item.ToString(), this));
                            }
                        }
                    }
                    #endregion
                }
            }
        }

        /// <summary>
        /// 绘制表情和文本
        /// </summary>
        private void DrawTextUI()
        {
            Paragraph paragraph = new Paragraph();
            
            foreach (var item in _contentList)
            {
                paragraph.Inlines.Add(item.CreateContent());
            }
            _richTextBox.Blocks.Add(paragraph);
        }

        #endregion

        #region Title DependencyProperty

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

        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Text", typeof(string), typeof(FaceTextBlock), new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnTextChanged)));

        private static void OnTextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            FaceTextBlock block = (FaceTextBlock)obj;
            if (block._richTextBox != null)
            {
                block.OnTextChanged();
            }
        }

        #endregion
    }
}

HcBaseTBContent.cs

namespace Controls.FaceTextBlock
{
    public class HcBaseTBContent
    {
        public string Text
        {
            get;
            set;
        }

        public Control Parent
        {
            get;
            set;
        }

        public HcBaseTBContent(string text,Control parent)
        {
            Text = text;
            Parent = parent;
        }

        public virtual Inline CreateContent()
        {
            return null;
        }
    }
}

HcFaceTBContent.cs

namespace Controls.FaceTextBlock
{
    public class HcFaceTBContent : HcBaseTBContent
    {
        public HcFaceTBContent(string text,Control parent)
            : base(text, parent)
        {
            
        }

        public override Inline CreateContent()
        {
            Grid grid = new Grid();
            grid.Height = Parent.FontSize + 8;
            grid.Width = Parent.FontSize + 8;

            Image image = new Image();
            image.Margin = new Thickness(0,0,0,-9);
            image.VerticalAlignment = VerticalAlignment.Bottom;
            image.Height = Parent.FontSize + 8;
            image.Width = Parent.FontSize + 8;
            Uri uri = new Uri(string.Format(@"/Controls;component/Images/Face/{0}.png", Text), UriKind.RelativeOrAbsolute);
            image.Source = new BitmapImage(uri);
            InlineUIContainer iuc = new InlineUIContainer();

            grid.Children.Add(image);
            iuc.Child = grid;
            return iuc;
        }
    }
}

HcTextTBContent.cs

namespace Controls.FaceTextBlock
{
    public class HcTextTBContent : HcBaseTBContent
    {
        public HcTextTBContent(string text, Control parent)
            : base(text, parent)
        {

        }

        public override Inline CreateContent()
        {
            Run r = new Run() { Text = Text };
            r.FontFamily = Parent.FontFamily;
            r.FontSize = Parent.FontSize;
            r.FontStretch = Parent.FontStretch;
            r.FontStyle = Parent.FontStyle;
            r.FontWeight = Parent.FontWeight;
            r.Foreground = Parent.Foreground;
            return r;
        }
    }
}
原文地址:https://www.cnblogs.com/CCSSPP/p/2919093.html