Copying Plain Text to the Clipboard
The ComponentOne RichTextBox control is part TextBox and part custom control. As of the 2012 v1 version, the control does not have built-in copying functionality, but if text resides on the clipboard, then you can paste it into C1RichTextBox for free. So in order to enable copying text, we must add it ourselves.
To put plain text on the clipboard the code would simply be:
// set clipboard text to plain text
Clipboard.SetText(c1RichTextBox1.SelectedText);
Next, we can create a custom round button that displays when the user selects some text in C1RichTextBox just as it would for a standard TextBox.
To create a round button we override the style to give it rounded corners (Border CornerRadius = 33).
<Style x:Key="RoundButtonStyle" TargetType="Button">
<Setter Property="Background" Value="{StaticResource PhoneBackgroundBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneBackgroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="33" Margin="{StaticResource PhoneTouchTargetOverhang}">
<ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
<ContentControl.RenderTransform>
<ScaleTransform x:Name="buttonScale" />
</ContentControl.RenderTransform>
</ContentControl>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
Then we can add a button to our page containing C1RichTextBox like this:
<Button x:Name="btnCopyPlainText"
Width="72"
Height="72"
Click="btnCopyPlainText_Click"
Margin="162,160, 0, 0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Style="{StaticResource RoundButtonStyle}"
Visibility="Collapsed" >
<Image x:Name="imgPlainText"
Source="Resources\Copy.png"
Stretch="Fill" />
</Button>
Notice that we are setting the HorizontalAlignment, VerticalAlignment and Margin. At run-time we will update the Margin to reflect the position of the selected text. To detect the selection changing we simply subscribe to the SelectionChanged event.
private void c1RichTextBox1_SelectionChanged(object sender, EventArgs e)
{
PositionCopyButton();
We can grab the Rect of the selected text by using the GetRectFromPosition method and passing in the SelectedTextStart and End positions. From this Rect we set the Left and Top margin values of our button so that it appears to float above the selected text.
private void PositionCopyButton()
{
if (!string.IsNullOrEmpty(c1RichTextBox1.SelectedText))
{
// get bounds of selected text
Rect rtStart = c1RichTextBox1.GetRectFromPosition(c1RichTextBox1.Selection.Start);
Rect rtEnd = c1RichTextBox1.GetRectFromPosition(c1RichTextBox1.Selection.End);
// center button above selected text
btnCopyPlainText.Margin = new Thickness(rtStart.X + ((rtEnd.X - rtStart.X) / 2) - btnCopyPlainText.Width / 2, rtStart.Y - btnCopyPlainText.Height, 0, 0);
btnCopyPlainText.Visibility = System.Windows.Visibility.Visible;
}
else
{
// hide button if no text to copy
btnCopyPlainText.Visibility = System.Windows.Visibility.Collapsed;
}
Then after we set the selected text to the clipboard we must set the Focus from the copy button back to C1RichTextBox. We can do this by simply calling the Focus method.
private void btnCopyPlainText_Click(object sender, RoutedEventArgs e)
{
// set clipboard text to plain text
Clipboard.SetText(c1RichTextBox1.SelectedText);
// keep focus on richtextbox
c1RichTextBox1.Focus();
}
That is it for copying plain text!