Great SL Competency Test Part 3 (Answer)

This is an answer to part 3 of the Great SL Competency Test, in which you were asked to demonstrate

  • Printing
  • Right Mouse Click
  • Clipboard Interaction

Printing

It is easy to make printing enormously complex, but basic printing requires just four steps:

  1. Instantiate a PrintDocument
  2. Wire up the event handler for the PrintDocument’s PrintPage event
  3. Call the PrintDocument’s Print event, optionally passing in a string to appear in the print queue
  4. Assign the element you want to print (which can include child elements)

To demonstrate this I created a simple page with an image and a text block and then a button to print,

<UserControl
    x:Class="SilverlightQuiz3.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="200"
    d:DesignWidth="200">

    <Grid
        x:Name="LayoutRoot"
        VerticalAlignment="Top"
        HorizontalAlignment="Left">
        <Grid.RowDefinitions>
            <RowDefinition
                Height="10*" />
            <RowDefinition
                Height="1*" />
            <RowDefinition
                Height="2*" />
        </Grid.RowDefinitions>

        <Image
            x:Name="theImage"
            Source="./WorksOnMyComputer.jpg"
            Stretch="Uniform"
            Width="150"
            Grid.Row="0" />
        <TextBlock
            x:Name="TheText"
            HorizontalAlignment="Center"
            Text="The WOMC Guarantee!"
            Grid.Row="1" />
        <Button
            x:Name="PrintMe"
            Content="Print"
            Width="75"
            Grid.Row="2" />

    </Grid>
</UserControl>

(Feel free to substitute any jpg you like, placed into the root directory of your project).

The code-behind reflects the four steps detailed above,

using System.Windows;
using System.Windows.Printing;

namespace SilverlightQuiz3
{
    public partial class MainPage
    {

        public MainPage()
        {
            InitializeComponent();
            PrintMe.Click += PrintMe_Click;
        }

        private void PrintMe_Click(object sender, RoutedEventArgs e)
        {
            var pDoc = new PrintDocument();
            pDoc.PrintPage += PDocPrintPage;
            pDoc.Print("Printing this demo page..."  );
        }

        void PDocPrintPage(object sender, PrintPageEventArgs e)
        {
            e.PageVisual = LayoutRoot;
        }

    }
}

Right Mouse Cllick

RightClick

The right mouse button is traditionally used for context-menus though that is not required.

If you do choose to respond to the right mouse button you can respond to either or both of the button down or button up events.

To create a context menu for this example, I use the Popup, and rather than implementing a full context menu, I chose to implement a simple tooltip to illustrate how the pop-up works.  Typically, however, rather than having a simple TextBlock, you might choose to use a ListBox of context-sensitive choices.

In any case, in the constructor, I instantiate the Popup and set event handlers on the button for its MouseRightButtonDown and MouseRightButtonUp events.

private Popup contextMenu;

public MainPage()
{
    InitializeComponent();
    contextMenu = new Popup();
    PrintMe.Click += PrintMe_Click;
    PrintMe.MouseRightButtonDown += PrintMe_MouseRightButtonDown;
    PrintMe.MouseRightButtonUp += PrintMe_MouseRightButtonUp;
}

When the user clicks down on the right mouse button I’ll open up the Popup and display the (abridged) context menu…

void PrintMe_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    var frameworkElement = e.OriginalSource as FrameworkElement;
    if (frameworkElement == null || contextMenu.IsOpen)
        return;
    var border = new Border
                 {
                     BorderBrush = new SolidColorBrush( Colors.Red ),
                     BorderThickness = new Thickness( 2.0 )
                 };

    var stackPanel = new StackPanel
                 {
                     Background =
                         new SolidColorBrush( Colors.Yellow )
                 };

    var textBlock = new TextBlock
                     {
                         Text = "Clicking will cause the entire page to print",
                         Margin = new Thickness( 5.0 )
                     };
    stackPanel.Children.Add(textBlock);
    border.Child = stackPanel;

    contextMenu.Child = border;

    contextMenu.VerticalOffset = 150;
    contextMenu.HorizontalOffset = 150;

    contextMenu.IsOpen = true;
    e.Handled = true;

}

Finally, when the user releases the button I’ll hide the menu…

void PrintMe_MouseRightButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    contextMenu.IsOpen = false;
    e.Handled = true;
}

Setting e.handled to true signals that I’ve handled the event and prevents other built-in handlers from running.

Clipboard

Clipboard Access Some of the controls have built in access to the clipboard, and you need not write any code.  For example, if you copy text from another source and then press Control-V while in a TextBox the contents of the clipboard will be pasted.  On the other hand, to support copying and pasting in additional controls, the Clipboard API provides the GetText and SetText methods. There are restrictions on these methods (they only support text, no graphics, and must be in response to a user-initiated action such as clicking or pressing a button, and the user must provide permission) but they do provide very simple access to the clipboard.  To illustrate, I’ve added a TextBox in a new bottom row to MainPage.xaml.

<TextBox
    x:Name="Target"
    Width="150"
    Grid.Row="3" />

To illustrate the first point, that there is built in support in TextBoxes, copy text from outside the application and then use control-v to paste it into the textBox.  To illustrate adding clipboard access, we’ll add code to allow the TextBlock’s text to be copied. Add an event handler in the constructor,

TheText.MouseLeftButtonDown += TheText_MouseLeftButtonDown;

The implementation of the event handler is very simple; just invoke the Clipboard’s SetText (you are setting the text into the clipboard) method,

void TheText_MouseLeftButtonDown(object sender,
    System.Windows.Input.MouseButtonEventArgs e)
{
    Clipboard.SetText(TheText.Text);
}

Scoring

Printing works: 20
Illustrate printing to a containing element: 10
React to Right Mouse Click: 20
Create any form of context menu: 20
Clipboard – no code: 10
Clipboard works with API: 20

About Jesse Liberty

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen online courses. His latest book, Building APIs with .NET will be released early in 2025. Liberty is a Senior SW Engineer for CNH and he was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Microsoft MVP.
This entry was posted in Community, Essentials, Patterns & Skills and tagged , . Bookmark the permalink.