silverlight 4之RichTextBox小試牛刀。
Silverlight4繼續(xù)摸索中,這回來到了RichTextBox,MS提供的類庫中提供了RichTextBox,但是并沒有帶工具欄,需要的話必須自己實現(xiàn),好在在Silverlight4的文檔中自帶一個叫Issue Tracker的示例程序,里面有應(yīng)用RichTextBox的例子,但是缺少了字體顏色,文本對齊和插入圖片的功能,我摸索著加上這三個功能,我是在Issue Tracker的例子上修改的,Issue Tracker在Silverlight4 文檔 - 入門 - Silverlight實例 - 行業(yè)示例中。
如圖所示:

首先我刪掉了ReadOnly按鈕,沒啥理由。
1, 選擇顏色
顏色面板用WrapPanel最合適不過了,只要按規(guī)律把R,G,B(紅綠藍(lán))不用組合全部塞入到Panel里就好了。
<UserControl xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" x:Class="Vega.Controls.ColorControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="240" d:DesignWidth="360">
<toolkit:WrapPanel x:Name="panel" Width="360" />
</UserControl>
public partial class ColorControl : UserControl
{
public EventHandler SelectColor;
public ColorControl()
{
InitializeComponent();
int granularity = 51;
for (int r = 0; r <= 255; r += granularity)
{
for (int g = 0; g <= 255; g += granularity)
{
for (int b = 0; b <= 255; b += granularity)
{
var rectangle =new Rectangle
{
Width = 20,
Height = 20,
Cursor = Cursors.Hand,
Fill = new SolidColorBrush(Color.FromArgb(255, (byte)r, (byte)g, (byte)b))
};
rectangle.MouseLeftButtonUp += new MouseButtonEventHandler(rectangle_MouseLeftButtonUp);
this.panel.Children.Add(rectangle);
}
}
}
}
private void rectangle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
this.Visibility = System.Windows.Visibility.Collapsed;
if (this.SelectColor != null)
{
this.SelectColor(sender, e);
}
}
}
顯示效果,顏色有點亂,還不知道有沒有更好算法:
加一個按鈕,點擊的時候顯示顏色面板。

將選擇的顏色應(yīng)用到Section:
private void colorButton_Click(object sender, RoutedEventArgs e)
{
this.color.Visibility = System.Windows.Visibility.Visible;
this.color.SelectColor = (senderObj, eventArgs) => {
var rectangle = senderObj as Rectangle;
this.richTextBox.Selection.ApplyPropertyValue(Run.ForegroundProperty, rectangle.Fill);
this.richTextBox.Focus();
};
}
private void colorButton_Click(object sender, RoutedEventArgs e)
{
this.color.Visibility = System.Windows.Visibility.Visible;
this.color.SelectColor = (senderObj, eventArgs) => {
var rectangle = senderObj as Rectangle;
this.richTextBox.Selection.ApplyPropertyValue(Run.ForegroundProperty, rectangle.Fill);
this.richTextBox.Focus();
};
}
2,對齊
加入個ComboBox先。
<ComboBox x:Name="alignmentComboBox"
Margin="0,2,2,2"
Height="25"
Width="65"
xmlns:sys="clr-namespace:System;assembly=mscorlib" SelectionChanged="alignmentComboBox_SelectionChanged">
<sys:String>左對齊</sys:String>
<sys:String>居中</sys:String>
<sys:String>右對齊</sys:String>
</ComboBox>
對齊也很簡單
private void alignmentComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
TextAlignment align = TextAlignment.Left;
switch (this.alignmentComboBox.SelectedItem.ToString())
{
case "左對齊":
align = TextAlignment.Left;
break;
case "居中":
align = TextAlignment.Center;
break;
case "右對齊":
align = TextAlignment.Right;
break;
}
this.richTextBox.Selection.ApplyPropertyValue(Block.TextAlignmentProperty, align);
}
記得修改richTextBox_SelectionChanged方法,在用戶移動光標(biāo)的時候修改ComboBox的選擇狀態(tài)
try
{
switch ((TextAlignment)this.richTextBox.Selection.GetPropertyValue(Block.TextAlignmentProperty))
{
case TextAlignment.Left:
this.alignmentComboBox.SelectedItem = "左對齊";
break;
case TextAlignment.Center:
this.alignmentComboBox.SelectedItem = "居中";
break;
case TextAlignment.Right:
this.alignmentComboBox.SelectedItem = "右對齊";
break;
}
}
catch { }
try
{
switch ((TextAlignment)this.richTextBox.Selection.GetPropertyValue(Block.TextAlignmentProperty))
{
case TextAlignment.Left:
this.alignmentComboBox.SelectedItem = "左對齊";
break;
case TextAlignment.Center:
this.alignmentComboBox.SelectedItem = "居中";
break;
case TextAlignment.Right:
this.alignmentComboBox.SelectedItem = "右對齊";
break;
}
}
catch { }
3,添加圖片功能
新建一個子窗口,用于添加,上傳圖片用。
這個窗口有三個屬性,圖片的URL,寬度和高度。
public string Source
{
get { return (string)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
public int ImageWidth
{
get { return (int)GetValue(ImageWidthProperty); }
set { SetValue(ImageWidthProperty, value); }
}
public int ImageHeight
{
get { return (int)GetValue(ImageHeightProperty); }
set { SetValue(ImageHeightProperty, value); }
}
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(string), typeof(ImageAttributeWindow), new PropertyMetadata("http://"));
public static readonly DependencyProperty ImageWidthProperty =
DependencyProperty.Register("ImageWidth", typeof(int), typeof(ImageAttributeWindow), new PropertyMetadata(100));
public static readonly DependencyProperty ImageHeightProperty =
DependencyProperty.Register("ImageHeight", typeof(int), typeof(ImageAttributeWindow), new PropertyMetadata(100));
窗口布局
<controls:ChildWindow xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" x:Class="Vega.Controls.ImageAttributeWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
Width="504" Height="178"
Title="圖片屬性" Name="imageAttributeWindow">
<toolkit:BusyIndicator x:Name="busyIndicator">
<Grid x:Name="LayoutRoot" Margin="2">
<Grid.RowDefinitions>
<RowDefinition Height="10" />
<RowDefinition Height="*" />
<RowDefinition Height="40" />
</Grid.RowDefinitions>
<Grid Grid.Row="1" Name="grid1">
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Right" Text="源地址:" VerticalAlignment="Center" />
<TextBlock HorizontalAlignment="Right" Text="寬度:" VerticalAlignment="Center" Grid.Row="1" />
<TextBlock HorizontalAlignment="Right" Text="寬度:" VerticalAlignment="Center" Grid.Row="2" />
<TextBox Grid.Column="1" Margin="2,2,60,2" Text="{Binding Path=Source, Mode=TwoWay, ElementName=imageAttributeWindow}" />
<Button Content="上傳" Width="50" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="2" Name="uploadButton" Click="uploadButton_Click" />
<toolkit:NumericUpDown HorizontalAlignment="Left" Grid.Column="1" Grid.Row="1" Margin="2,2,0,0" Value="{Binding Path=ImageWidth, Mode=TwoWay, ElementName=imageAttributeWindow}" Maximum="1000" Height="22" VerticalAlignment="Top" />
<toolkit:NumericUpDown HorizontalAlignment="Left" Grid.Column="1" Grid.Row="2" Margin="2" Value="{Binding Path=ImageHeight, Mode=TwoWay, ElementName=imageAttributeWindow}" Maximum="1000" />
</Grid>
<Button x:Name="CancelButton" Content="取消" Click="CancelButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="2" />
<Button x:Name="OKButton" Content="確定" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="2" />
</Grid>
</toolkit:BusyIndicator>
</controls:ChildWindow>
我把圖片URL,寬度,高度都和子窗口的Source,ImageWidth,ImageHeight綁定了起來,效果如下

上傳圖片的代碼
private void uploadButton_Click(object sender, RoutedEventArgs e)
{
var fileDialog = new OpenFileDialog()
{
Filter = "圖片(.jpg)|*.jpg|圖片(.jpeg)|*.jpeg|圖片(.png)|*.png",
Multiselect = false
};
var result = fileDialog.ShowDialog();
if (result.HasValue && result.Value)
{
using (var stream = fileDialog.File.OpenRead())
{
var imgSource = new BitmapImage();
imgSource.SetSource(stream);
var bitmap = new WriteableBitmap(imgSource);
this.ImageWidth = bitmap.PixelWidth;
this.ImageHeight = bitmap.PixelHeight;
stream.Seek(0, SeekOrigin.Begin);
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
this.busyIndicator.IsBusy = true;
var op = this.uploadContext.Upload(bytes, fileDialog.File.Extension);
op.Completed += (opSender, opE) => {
var source = Application.Current.Host.Source;
this.Source = String.Format("{0}://{1}:{2}{3}", source.Scheme, source.Host, source.Port, op.Value);
this.busyIndicator.IsBusy = false;
};
}
}
}
負(fù)責(zé)上傳的uploadContext在上一篇隨筆 http://www.rzrgm.cn/subwayline13/archive/2010/09/01/1813836.html 有提到,很簡單。區(qū)別是,silvelight 客戶端有加上通過WriteableBitmap讀取寬度和高度方法,讀取到長和寬之后記得歸位stream.Seek(0, SeekOrigin.Begin);不然stream.Read不到,因為指針已經(jīng)到尾部了。
調(diào)用添加圖片子窗口的代碼
private void imageButton_Click(object sender, RoutedEventArgs e)
{
var window = new ImageAttributeWindow();
window.Closed += (senderObj, ea) =>
{
if (!window.DialogResult.HasValue || !window.DialogResult.Value)
{
return;
}
InlineUIContainer container = new InlineUIContainer();
container.Child = new Image()
{
Stretch = Stretch.Uniform,
Width = window.ImageWidth,
Height = window.ImageHeight,
Source = new BitmapImage(new Uri(window.Source,UriKind.Absolute))
};
this.richTextBox.Selection.Insert(container);
};
window.Show();
}
網(wǎng)上搜了一下,發(fā)現(xiàn)RichTextBox還不少,有一個免費開源的http://www.vectorlight.net/demos/richtextbox.aspx,不過存儲的不是XAML的,是自定義的XML的。

浙公網(wǎng)安備 33010602011771號