Note – these posts are put together after a short time with Silverlight 4 as a way of providing pointers to some of the new features that Silverlight 4 has to offer. I’m posting these from the PDC as Silverlight 4 is announced for the first time so please bear that in mind when working through these posts.
Silverlight 4 has a much richer way of displaying “documents” in that it provides a RichTextArea control. In some ways this is analogous to a lightweight version of the document support in WPF.
There’s a new System.Windows.Documents namespace which contains classes such as;
- Paragraph
- Hyperlink
- Inline
- InlineUIContainer
- LineBreak
- Run
- Span
from which you can construct pretty rich documents for display in the RichTextArea. The RichTextArea has a content property called Blocks which is a collection of Block ( which have alignment ) which looks to translate into on concrete type of Paragraph right now. A Paragraph has a collection of Inlines which can be Span, InlineUIContainer, Run, LineBreak, Hyperlink ( there may be more, my exploration stopped there ).
This means that I can put together a document for display in a RichTextArea;
<UserControl x:Class="SilverlightApplication27.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"> <Grid x:Name="LayoutRoot" Background="White"> <RichTextArea TextWrapping="Wrap" IsReadOnly="False"> <Paragraph>The quick brown fox jumped over the lazy dog</Paragraph> <Paragraph TextDecorations="Underline" FontSize="24" TextAlignment="Right" FontFamily="Courier New">The quick brown fox jumped over the lazy dog </Paragraph> <Paragraph> The quick brown fox jumped over the lazy dog <LineBreak /> The quick brown fox jumped over the lazy dog <LineBreak /> <Italic> The quick brown fox jumped over the lazy dog </Italic> </Paragraph> <Paragraph> The quick brown fox jumped over the lazy dog <InlineUIContainer> <Rectangle Margin="2" Fill="Red" Width="48" Height="12" /> </InlineUIContainer>with a red rectangle </Paragraph> <Paragraph> <Hyperlink NavigateUri="http://www.microsoft.com" TargetName="">Go to Microsoft.com</Hyperlink> </Paragraph> <Paragraph> <Run Text="The quick brown " /> <Run >fox jumped over the lazy dog</Run> </Paragraph> <Paragraph> <Span FontSize="24"> <Run>The quick brown fox jumped over the lazy dog</Run> <Run>The quick brown fox jumped over the lazy dog</Run> </Span> </Paragraph> </RichTextArea> </Grid> </UserControl>
where you can see some of Paragraph, Span, Run, Hyperlink, InlineUIContainer and one or two others being exercised a little. Of all of those, InlineUIContainer perhaps deserves special call out as it allows me to embed arbitrary UI into the document.
This gives me a UI;
and this isn’t read-only, I can wander into the UI and start to edit the content;
and even delete that red rectangle when I come to it with the cursor. There’s also a level of undo/redo support in there.
Now, naturally, all of what has been created in XAML is programmable from code that I put behind of that UI so all of those types like Paragraph, Run etc. can be coded against and animated, bound and so on ( at least where the types/properties allow binding, animation ).
We can also put other Silverlight elements into those InlineUIContainer elements so if I add something simple like a Button;
<UserControl x:Class="SilverlightApplication27.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"> <Grid x:Name="LayoutRoot" Background="White"> <RichTextArea TextWrapping="Wrap" IsReadOnly="False"> <Paragraph> This is some text and then there's a piece of UI <LineBreak /> <InlineUIContainer> <Button Content="Click Me" Click="Button_Click"/> </InlineUIContainer> <LineBreak /> and then there's some more text and some space for more still; <LineBreak /> <Run x:Name="runToModify" /> </Paragraph> </RichTextArea> </Grid> </UserControl>
then, with these default settings the Button will show up but is disabled because the RichTextArea is in editable mode. If I move it to read-only mode;
<RichTextArea TextWrapping="Wrap" IsReadOnly="True">
then the Button becomes usable and with some code behind;
public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { runToModify.Text = "dynamically added some more text"; } }
does exactly what you’d expect it to do when I click the Button – adds the extra text;
There’s a bunch of events on the control such as TextInputEvent, TextInputStartEvent, TextInputUpdateEvent and there’s also a Selection property that you can grab hold of.
I suspect there’s a lot more reading to do on this one but it’s great to have a lot more flexibility around the display of text and to then go beyond that by allowing for rich user interface elements to be embedded into that display.
It does raise some interesting questions though because I can see scenarios where you could use UI elements containing text or a RichTextArea containing UI elements to present the same data and I guess it’ll take some time to figure out which approach is “best” in different situations.