摘要:客製化RichTextBox!
Silverlight有提供一個好用的TextBox,叫做RichTextBox,這個UI可以放入HyperLink,圖片之類的,比原本的TextBox強多了,不過只能讀取,並不能輸入,但是是拿來顯示就很強大了。
在Google搜尋時大都是講解怎麼用xaml調教這個RichTextBox,但是如果我們想要binding的話,相關的文章也是有,只不過是在已經調教好的Paragraph放入binding的東西,我這邊是要分享自己去用code生成Paragraph!
首先,silverlight有個Behavior這個東西,可以把一些常用的元件封裝成可重復使用的元件,我們現在的需求時,當RichTextBox接收到要輸出的訊息時,就要生成Paragraph!
所以我們先創個新的類別,叫做ConvertRichTextBoxContentBehavior好了,然後讓它繼承RichTextBox的行為
public class ConvertRichTextBoxContentBehavior : Behavior< richtextbox >
再來我們要binding輸出的訊息,所以弄個可對外的屬性
public static DependencyProperty ContentProperty
= DependencyProperty.RegisterAttached(
"Content", typeof(string),
typeof(RichTextBox),
new PropertyMetadata(null, OnContentChanged));
public string Content
{
set
{
SetValue(ContentProperty, value);
}
get
{
return (string)GetValue(ContentProperty);
}
}
超連結的顏色屬性
public static DependencyProperty LinkColorProperty
= DependencyProperty.RegisterAttached("LinkColor", typeof(SolidColorBrush), typeof(RichTextBox), null);
public SolidColorBrush LinkColor
{
set
{
SetValue(LinkColorProperty, value);
}
get
{
return (SolidColorBrush)GetValue(LinkColorProperty);
}
}
接下來,當binding屬性改變的時候,就要開始做處理了!所以要
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
string content = e.NewValue as string;
ConvertRichTextBoxContentBehavior sender = d as ConvertRichTextBoxContentBehavior;
if (!string.IsNullOrWhiteSpace(content) && d != null)
{
sender.ConvertContent(content);
}
}
轉換的方法
void ConvertContent(string content)
{
try
{
// 辨識
// 網址:(((http://)|(https://)+)[^(\s)]{1,})
// Email:([a-zA-Z0-9_-]+@\w+\.[a-z]+(\.[a-z]+)?)
// 電話:(\d{7,})
// 圖片:(\[[^\]]*\])
Regex httpRegex = new Regex(@"(((http://)|(https://)+)[^(\s)]{1,})|([a-zA-Z0-9_-]+@\w+\.[a-z]+(\.[a-z]+)?)|(\d{7,})|(\[[^\]]*\])");
string target = content as string;
Paragraph rootParagraph = new Paragraph();
MatchCollection mc = httpRegex.Matches(target);
if (mc.Count != 0)
{
int flag = 0;
for (int i = 0; i < mc.Count; i++)
{
if (mc[i].Index != 0)
{
Run r = new Run();
r.Foreground = this.AssociatedObject.Foreground;
r.Text = target.Substring(flag, mc[i].Index - flag);
flag = flag + r.Text.Length;
rootParagraph.Inlines.Add(r);
}
Hyperlink hyperLink = new Hyperlink();
hyperLink.Foreground = this.LinkColor;
hyperLink.MouseOverForeground = this.LinkColor;
if (mc[i].Value.Contains("@"))
{
hyperLink.Click += new RoutedEventHandler(hyperLink_EmailClick);
Run r = new Run();
r.Text = mc[i].Value;
hyperLink.Inlines.Add(r);
rootParagraph.Inlines.Add(hyperLink);
flag = flag + mc[i].Length;
}
else if (mc[i].Value.Contains("http://") || mc[i].Value.Contains("https://"))
{
//URL
hyperLink.TargetName = "_blank";
hyperLink.NavigateUri = new Uri(mc[i].Value);
Run r = new Run();
r.Text = mc[i].Value;
hyperLink.Inlines.Add(r);
rootParagraph.Inlines.Add(hyperLink);
flag = flag + mc[i].Length;
}
else if (mc[i].Value.Contains("["))
{
// 表情符號
string strImg = mc[i].Value.Replace("[", "").Replace("]", "");
Image image = new Image();
StreamResourceInfo resourceInfo = Application.GetResourceStream(new System.Uri("Images/emotion/orz.png", UriKind.Relative));
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(resourceInfo.Stream);
image.Height = bitmapImage.PixelHeight;
image.Width = bitmapImage.PixelWidth;
image.Source = bitmapImage;
InlineUIContainer container = new InlineUIContainer();
container.Child = image;
rootParagraph.Inlines.Add(container);
flag += mc[i].Length;
}
else
{
hyperLink.Click += new RoutedEventHandler(hyperLink_PhoneClick);
Run r = new Run();
r.Text = mc[i].Value;
hyperLink.Inlines.Add(r);
rootParagraph.Inlines.Add(hyperLink);
flag = flag + mc[i].Length;
}
}
if (flag < target.Length - 0)
{
Run r = new Run();
r.Text = target.Substring(flag, target.Length - flag);
flag = flag + r.Text.Length;
rootParagraph.Inlines.Add(r);
}
}
else
{
rootParagraph.Inlines.Add((new Run()).Text = target);
}
this.AssociatedObject.Blocks.Clear();
this.AssociatedObject.Blocks.Add(rootParagraph);
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine("Exception in Custom.RichTextBox.OnContentChanged:" + e.Message);
}
}
private void hyperLink_EmailClick(object sender, RoutedEventArgs e)
{
EmailComposeTask ect = new EmailComposeTask();
Hyperlink h = sender as Hyperlink;
ect.To = (h.Inlines[0] as Run).Text;
ect.Show();
}
private void hyperLink_PhoneClick(object sender, RoutedEventArgs e)
{
PhoneCallTask pct = new PhoneCallTask();
Hyperlink h = sender as Hyperlink;
pct.PhoneNumber = (h.Inlines[0] as Run).Text;
pct.Show();
}
裡面的有辨識Email,Http,電話號碼,還有[123]這類的資訊,所以也可以秀出圖片!
要怎麼使用呢?
<RichTextBox>
<interactivity:Interaction.Behaviors>
<localHelpers:ConvertRichTextBoxContentBehavior Content="{Binding Path=MsgBody}" LinkColor="White">
</localHelpers:ConvertRichTextBoxContentBehavior>
</interactivity:Interaction.Behaviors>
</RichTextBox>
記得要引入參考System.Windows.Interactivity