《RichTextBox 》——— RichTextBox 数据绑定___代码添加
WP7 里面 richtextbox 不支持 HTML 也不支持 RTF 不支持 HTML 。 写 XAML 你会发现他有套自己的解析标准。。。。 悲催
同时 ricttextbox 也没啥 可以用来 绑定 内容 的属性 。。。。 这情况下 我们 的 ViewModel 中的类人要绑定打richtextbox 怎么办呢 ???
下面是我遭遇的实际问题 :
在做喂饭 (饭否客户端) 时 拿到 的微博内容 是一个字符串 里面 带有 @ # 还有url什的 。。 我想要展现这条微博 同时 @ # URL 要做成可点击的 link, 这是我考虑到使用 RICHTEXTBOX ,然后。。。 额。。。 就发生上述地问题。。。
刚开始思考这个问题时我第一想法是 重写 空间 在里面 做一个可以进行数据绑定的 动态属性 然后 在动态属性的Change 事件中 解析 动态属性的内容 在控件的blocks 添加要展现的内容 。。。
然后 就产生了下面 这样奇葩一样的控件
1 using System; 2 using System.Net; 3 using System.Windows; 4 using System.Windows.Controls; 5 using System.Windows.Documents; 6 using System.Windows.Ink; 7 using System.Windows.Input; 8 using System.Windows.Media; 9 using System.Windows.Media.Animation; 10 using System.Windows.Shapes; 11 using System.Text.RegularExpressions; 12 using System.ComponentModel; 13 14 namespace WeiFan.UI.CustomeControl 15 { 16 public class FanFouContentBox :System.Windows.Controls.RichTextBox 17 { 18 /// <summary> 19 /// 设置DependencyProperty属性 20 /// </summary> 21 public DependencyProperty ContentProperty; 22 /// <summary> 23 /// 设置Content的访问器 24 /// </summary> 25 public string Content 26 { 27 set 28 { 29 SetValue(ContentProperty, value); 30 } 31 get 32 { 33 return (string)GetValue(ContentProperty); 34 } 35 } 36 37 public FanFouContentBox() 38 { 39 //设置DependencyProperty的默认描述 40 PropertyMetadata _metadata = new PropertyMetadata(string.Empty, OnContentChanged); ; 41 ////设置默认值勤 42 //_metadata.DefaultValue = null; 43 ////设置是否影响布局 44 //_metadata.AffectsMeasure = true; 45 ////设置是否影响到其子控件 46 //_metadata.Inherits = true; 47 ////设置属性变化时的处理方法 48 //_metadata.PropertyChangedCallback += OnImagePropertyChanged; 49 50 ContentProperty = DependencyProperty.Register("Content", typeof(string), typeof(FanFouContentBox), _metadata); 51 Content = this.Xaml; 52 } 53 54 /// <summary> 55 /// 设置回调方法 56 /// </summary> 57 /// <param name="obj"></param> 58 /// <param name="args"></param> 59 void OnContentChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) 60 { 61 try 62 { 63 Regex rootRegex = new Regex(@"(((http://)|(ftp://)|(https://)|(zune://)+)[^(\s)]{1,})|(#[^\s]{1,}#)|(((@{1})[^(\s|@)]{1,}))");//(@"(([http|ftp|https|zune]+://[^\s]*)|(#[^\s]*#)|)"); 64 string target = args.NewValue as string;//@"http://t.cn/heMORnhttp://t.cn/heMORn 万能Url正则表达式[http,ftp,news,telnet.....]——史上最全Url正则表达式(基于RFC1738?) - 正则表达式 - 拼吾爱程序人生 http://t.cn/heMORn 1sfsdfsdfsdfsdfsdfsdfsdfdsfsdfsfsdfsdfsfsfsfsf1 Regex Tester – RegexPal http://regexpa 1sdfsfsdfsdfsdfs1";//string.Empty; 65 target = target.Replace("<b>", string.Empty); 66 target = target.Replace("</b>", string.Empty); 67 target = System.Net.HttpUtility.HtmlDecode(target); 68 Paragraph rootParagraph = new Paragraph(); 69 70 MatchCollection mc = rootRegex.Matches(target); 71 if (mc.Count != 0) 72 { 73 int flag = 0; 74 for (int i = 0; i < mc.Count; i++) 75 { 76 if (mc[i].Index != 0) 77 { 78 Run r = new Run(); 79 r.Foreground = this.Foreground; 80 r.Text = target.Substring(flag, mc[i].Index - flag); 81 82 flag = flag + r.Text.Length; 83 rootParagraph.Inlines.Add(r); 84 } 85 86 //Regex urlRegex = new Regex(@"[http|ftp|https|zune]+://[^\s]*"); 87 //Regex trendRegex = new Regex(@"#[^\s]*#"); 88 89 90 91 92 if (mc[i].Value.StartsWith("#")) 93 { 94 //热点 95 if (mc[i].Value.Length > 2) 96 { 97 Hyperlink h = new Hyperlink(); 98 //h.TargetName = "_blank"; 99 System.Collections.Generic.Dictionary<string, string> param = new System.Collections.Generic.Dictionary<string, string>(); 100 101 string text = (mc[i].Value).Remove(0, 1); 102 text = text.Remove(text.Length - 1, 1); 103 param.Add("query", text); 104 105 h.NavigateUri = new Uri("/SearchResult.xaml?" + WeiFan.Utility.HttpUtility.URLQueryStringBuilder(param), UriKind.Relative); 106 107 Run r = new Run(); 108 r.Text = mc[i].Value; 109 h.Inlines.Add(r); 110 rootParagraph.Inlines.Add(h); 111 flag = flag + mc[i].Length; 112 } 113 } 114 else if (mc[i].Value.StartsWith("@")) 115 { 116 System.Collections.Generic.Dictionary<string, string> param = new System.Collections.Generic.Dictionary<string, string>(); 117 param.Add("content", mc[i].Value); 118 //PhoneApplicationFrame.Navigate(new Uri("/PublishStatus.xaml?" + WeiFan.Utiltiy.HttpUtility.URLQueryStringBuilder(param), UriKind.Relative)); 119 120 Hyperlink h = new Hyperlink(); 121 122 h.NavigateUri = new Uri("/PublishStatus.xaml?" + WeiFan.Utility.HttpUtility.URLQueryStringBuilder(param), UriKind.Relative); 123 124 Run r = new Run(); 125 r.Text = mc[i].Value; 126 h.Inlines.Add(r); 127 rootParagraph.Inlines.Add(h); 128 flag = flag + mc[i].Length; 129 } 130 131 else 132 { 133 //URL 134 Hyperlink h = new Hyperlink(); 135 h.TargetName = "_blank"; 136 h.NavigateUri = new Uri(mc[i].Value); 137 Run r = new Run(); 138 r.Text = mc[i].Value; 139 h.Inlines.Add(r); 140 rootParagraph.Inlines.Add(h); 141 flag = flag + mc[i].Length; 142 } 143 144 145 146 } 147 if (flag < target.Length - 1) 148 { 149 Run r = new Run(); 150 r.Text = target.Substring(flag, target.Length - flag); 151 flag = flag + r.Text.Length; 152 rootParagraph.Inlines.Add(r); 153 } 154 } 155 else 156 { 157 rootParagraph.Inlines.Add((new Run()).Text = target); 158 } 159 this.Blocks.Clear(); 160 this.Blocks.Add(rootParagraph); 161 } 162 catch (Exception e) 163 { 164 System.Diagnostics.Debug.WriteLine("Exception in Custom.RichTextBox.OnContentChanged:" + e.Message); 165 } 166 } 167 168 169 } 170 }
不过 这方法 有个 非常蛋疼的缺陷就是 。。。 我这里涉及到解析多种文本 那就蛋疼 了 。。。 每种 挨个重写一次 。。。
后来 看到了 behavior 这种好东西 。。。 意识到 可以通过 behavior 吧 解析 和 动态属性给剥离出来
直接上代码
1 using System; 2 using System.Net; 3 using System.Text.RegularExpressions; 4 using System.Windows; 5 using System.Windows.Controls; 6 using System.Windows.Documents; 7 using System.Windows.Ink; 8 using System.Windows.Input; 9 using System.Windows.Media; 10 using System.Windows.Media.Animation; 11 using System.Windows.Shapes; 12 using System.Windows.Interactivity; 13 14 namespace WeiFan.UI.Behavior 15 { 16 public class ConvertFanFouContentBehavior :Behavior<RichTextBox> 17 { 18 public static DependencyProperty ContentProperty 19 = DependencyProperty.RegisterAttached( 20 "Content", typeof(string), 21 typeof(RichTextBox), 22 new PropertyMetadata(null, OnContentChanged)); 23 24 public string Content 25 { 26 set 27 { 28 SetValue(ContentProperty, value); 29 } 30 get 31 { 32 return (string)GetValue(ContentProperty); 33 } 34 } 35 36 public bool IsEnable { get; set; } 37 38 public ConvertFanFouContentBehavior() 39 { 40 IsEnable = true; 41 42 } 43 44 private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 45 { 46 string content = e.NewValue as string; 47 48 ConvertFanFouContentBehavior sender = d as ConvertFanFouContentBehavior; 49 50 if (!string.IsNullOrWhiteSpace(content) && d!=null) 51 { 52 sender.ConvertFanfouContent(content); 53 } 54 } 55 56 void ConvertFanfouContent(string content) 57 { 58 try 59 { 60 Regex rootRegex = new Regex(@"(((http://)|(ftp://)|(https://)|(zune://)+)[^(\s)]{1,})|(#[^\s]{1,}#)|(((@{1})[^(\s|@)]{1,}))");//(@"(([http|ftp|https|zune]+://[^\s]*)|(#[^\s]*#)|)"); 61 string target = content as string;//@"http://t.cn/heMORnhttp://t.cn/heMORn 万能Url正则表达式[http,ftp,news,telnet.....]——史上最全Url正则表达式(基于RFC1738?) - 正则表达式 - 拼吾爱程序人生 http://t.cn/heMORn 1sfsdfsdfsdfsdfsdfsdfsdfdsfsdfsfsdfsdfsfsfsfsf1 Regex Tester – RegexPal http://regexpa 1sdfsfsdfsdfsdfs1";//string.Empty; 62 target = target.Replace("<b>", string.Empty); 63 target = target.Replace("</b>", string.Empty); 64 target = System.Net.HttpUtility.HtmlDecode(target); 65 Paragraph rootParagraph = new Paragraph(); 66 67 MatchCollection mc = rootRegex.Matches(target); 68 if (mc.Count != 0) 69 { 70 int flag = 0; 71 for (int i = 0; i < mc.Count; i++) 72 { 73 if (mc[i].Index != 0) 74 { 75 Run r = new Run(); 76 r.Foreground = this.AssociatedObject.Foreground; 77 r.Text = target.Substring(flag, mc[i].Index - flag); 78 79 flag = flag + r.Text.Length; 80 rootParagraph.Inlines.Add(r); 81 } 82 83 //Regex urlRegex = new Regex(@"[http|ftp|https|zune]+://[^\s]*"); 84 //Regex trendRegex = new Regex(@"#[^\s]*#"); 85 86 87 88 89 if (mc[i].Value.StartsWith("#")) 90 { 91 //热点 92 if (mc[i].Value.Length > 2) 93 { 94 Hyperlink h = new Hyperlink(); 95 //h.TargetName = "_blank"; 96 System.Collections.Generic.Dictionary<string, string> param = new System.Collections.Generic.Dictionary<string, string>(); 97 98 string text = (mc[i].Value).Remove(0, 1); 99 text = text.Remove(text.Length - 1, 1); 100 param.Add("query", text); 101 102 h.NavigateUri = new Uri("/SearchResult.xaml?" + WeiFan.Utility.HttpUtility.URLQueryStringBuilder(param), UriKind.Relative); 103 104 Run r = new Run(); 105 r.Text = mc[i].Value; 106 h.Inlines.Add(r); 107 rootParagraph.Inlines.Add(h); 108 flag = flag + mc[i].Length; 109 } 110 } 111 else if (mc[i].Value.StartsWith("@")) 112 { 113 System.Collections.Generic.Dictionary<string, string> param = new System.Collections.Generic.Dictionary<string, string>(); 114 param.Add("content", mc[i].Value); 115 //PhoneApplicationFrame.Navigate(new Uri("/PublishStatus.xaml?" + WeiFan.Utiltiy.HttpUtility.URLQueryStringBuilder(param), UriKind.Relative)); 116 117 Hyperlink h = new Hyperlink(); 118 119 h.NavigateUri = new Uri("/PublishStatus.xaml?" + WeiFan.Utility.HttpUtility.URLQueryStringBuilder(param), UriKind.Relative); 120 121 Run r = new Run(); 122 r.Text = mc[i].Value; 123 h.Inlines.Add(r); 124 rootParagraph.Inlines.Add(h); 125 flag = flag + mc[i].Length; 126 } 127 128 else 129 { 130 //URL 131 Hyperlink h = new Hyperlink(); 132 h.TargetName = "_blank"; 133 h.NavigateUri = new Uri(mc[i].Value); 134 Run r = new Run(); 135 r.Text = mc[i].Value; 136 h.Inlines.Add(r); 137 rootParagraph.Inlines.Add(h); 138 flag = flag + mc[i].Length; 139 } 140 141 142 143 } 144 if (flag < target.Length - 1) 145 { 146 Run r = new Run(); 147 r.Text = target.Substring(flag, target.Length - flag); 148 flag = flag + r.Text.Length; 149 rootParagraph.Inlines.Add(r); 150 } 151 } 152 else 153 { 154 rootParagraph.Inlines.Add((new Run()).Text = target); 155 } 156 this.AssociatedObject.Blocks.Clear(); 157 this.AssociatedObject.Blocks.Add(rootParagraph); 158 } 159 catch (Exception e) 160 { 161 System.Diagnostics.Debug.WriteLine("Exception in Custom.RichTextBox.OnContentChanged:" + e.Message); 162 } 163 } 164 165 } 166 }
然后嘛。。。
在 XMAL 里面使用 这个 behavior
1 <RichTextBox x:Name="rtb_content" FontSize="24" Width="365" TextWrapping="Wrap" > 2 <i:Interaction.Behaviors> 3 <Behavior:ConvertFanFouContentBehavior Content="{Binding Path=Content}"></Behavior:ConvertFanFouContentBehavior> 4 </i:Interaction.Behaviors> 5 </RichTextBox>
然后 ,。。。 就没有 然后了