June 29, 2012 08:54 by
Scott
In this article, I am going to explain how to design a RichTextBox in Silverlight. This example also demonstrates the RichTextBox control as well. It is easy to formatt a Silverlight RichTextBox at design time through XAML. In this example I have used an image to illustrate the example clearly.
<UserControl x:Class="SilverlightApplication3.MainPage"
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="300" d:DesignWidth="400" DataContext="{Binding}">
<Grid x:Name="LayoutRoot" Background="White" Height="450" Width="550">
<RichTextBox HorizontalAlignment="Left" Margin="10,12,0,0" Name="contentBox" VerticalAlignment="Top" Height="330" Width="390" IsReadOnly="True" Background="#FFFFFF69">
<Paragraph FontFamily="Arial" FontSize="12" TextAlignment="Justify">
This photograph shows a
<Run Text=" blue hills " FontStyle="Italic" FontWeight="ExtraBold" /> belongs to the
<Run Text=" high " Foreground="blue" FontWeight="ExtraBold"/> graphic photography. High graphic photography requires a great deal of precision.
<LineBreak/>
<InlineUIContainer>
<Image Height="143" HorizontalAlignment="Left" Margin="144,82,0,0" Name="images" Stretch="Uniform" VerticalAlignment="Top" Width="196" Source="/SilverlightApplication3;component/Images/Blue%20hills.jpg" />
</InlineUIContainer>
<LineBreak/>
<LineBreak/> |
</Paragraph>
</RichTextBox>
</Grid>
</UserControl>
Now I am going to explain the code so that it can be easily understood. It creates a RichTextBox, with some text and an image. To place and format the text, I first use the Paragraph element, then the Run element. Note that the Paragraph element also has a Foreground property but which I have not used here. In this I use the Run element which is useful to format text. The RichTextBox control also allows you to add elements of type Bold, Underline etc.The Run element derives from the Inline element, an Inline cannot be used directly within a RichTextBox control, however, you can use the Run element.
The LineBreak element is used to introduce line breaks.
The Image is placed inside the InlineUIContainer.
InlineUIContainer: A mandatory child element that is used to place an Image in the RichTextBox control.
You can have as many Paragraph and Run elements as you want, in a RichTextBox control. Using a combination of Paragraph and Run elements, you can format the text in various ways.
The output of the above application is shown below:
June 13, 2012 08:26 by
Scott
One of the new features included with the Silverlight 5 RC is the ability to interact with Platform Invocation Services, or PInvoke for short. This functionality allows managed code, like your Silverlight application, to make calls to unmanaged code like the C++ code that exists in DLLs on your system. PInvoke can be quite complex and covers a lot of different scenarios, so I've focused on a simple scenario to help you get started. You can learn more about PInvoke by reading this MSDN tutorial.
In this post, I will show you how to build a Silverlight Out-of-Browser (OOB) application that uses the native DLLs on your machine to play "beeps." With modern versions of Windows 7, the beeps have evolved into complex sounds that you can assign to various functions. Create a new Silverlight application called "PInvoke," set it to run out of browser and be sure to check the box that indicates it requires elevated trust.
Take a look at the MessageBeep function. It is documented here. The first thing you'll notice is that the type of beep or sound to play is not very friendly as it is passed in as an unsigned integer. Based on the documentation, you can create the following enumeration to simplify things and expose a few key types:
1 public enum BeepTypes : uint
2 {
3 Ok = 0x00000000,
4 Error = 0x00000010,
5 Warning = 0x00000030,
6 Information = 0x00000040
7 }
To make it easy to take a string and cast it to the enumeration value, add this extension method as well:
01 public static class BeepTypeExtensions
02 {
03 public static BeepTypes AsBeepTypeEnum(this string beepType)
04 {
05 BeepTypes beepTypeEnum;
06 return Enum.TryParse(beepType, true, out beepTypeEnum)
07 ? beepTypeEnum
08 : BeepTypes.Error;
09 }
10 }
It is always good practice to encapsulate your calls to unmanaged code in a managed class. This limits the exposure and dependency on PInvoke. It also allows you to write more portable code because you can implement the calls in managed code or simply stub out empty methods for targets that don't support the PInvoke implementation. Here is a simple contract to play a sound:
1 public interface ISoundPlayer
2 {
3 void PlaySound(BeepTypes type);
4 }
Now for the implementation. Create a class called SoundPlayer. The documentation gives you the message signature and the DLL that the method is located in. Bridging to the method in this example is very easy. First, include a using statement for System.Runtime.InteropServices. This is where the PInvoke bridge lives. Next, simply define the message signature as a static extern and import the DLL:
1 [DllImport("User32.dll")]
2 private static extern Boolean MessageBeep(UInt32 beepType);
Implement the contract and call the method you just imported using PInvoke:
1 public void PlaySound(BeepTypes type)
2 {
3 if (!MessageBeep((UInt32) type))
4 {
5 throw new Exception("Beep failed!");
6 }
7 }
That's all there is to it! Now wire up some Xaml in the main page to host four buttons:
01 <Grid x:Name="LayoutRoot" Background="White">
02 <Grid.RowDefinitions>
03 <RowDefinition Height="1*"/>
04 <RowDefinition Height="1*"/>
05 </Grid.RowDefinitions>
06 <Grid.ColumnDefinitions>
07 <ColumnDefinition Width="1*"/>
08 <ColumnDefinition Width="1*"/>
09 </Grid.ColumnDefinitions>
10 <Button x:Name="Ok" Content="OK" Grid.Row="0" Grid.Column="0" Click="Button_Click"/>
11 <Button x:Name="Error" Content="Error" Grid.Row="0" Grid.Column="1" Click="Button_Click"/>
12 <Button x:Name="Warning" Content="Warning" Grid.Row="1" Grid.Column="0" Click="Button_Click"/>
13 <Button x:Name="Information" Content="Information" Grid.Row="1" Grid.Column="1" Click="Button_Click"/>
14 </Grid>
Make sure that the name of the button matches the name of the enum. In the code-behind for the main page, create an instance of the sound player:
1 private readonly ISoundPlayer _soundPlayer = new SoundPlayer();
Now you can implement the button click event. Simply cast the name of the button to the enumeration and call the method on your managed class:
1 private void Button_Click(object sender, RoutedEventArgs e)
2 {
3 var button = sender as Button;
4 if (button == null)
5 {
6 return;
7 }
8 _soundPlayer.PlaySound(button.Name.AsBeepTypeEnum());
9 }
That's it! Run the application in OOB mode and you will be able to press the buttons and hear your default Windows sounds play. If you change your theme or override the sounds, the application will play the correct sounds because it is bridging to the unmanaged code and asking the operating system to play the sound rather than trying to play it from a resource embedded within the Silverlight application.
Hopefully this light example will help you get started. PInvoke has a number of uses from interfacing directly with USB ports to enumerating drives and devices on the host system. It certainly opens the door to a new realm of possibilities with Silverlight.