달력

11

« 2024/11 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
2016. 10. 15. 18:56

WPF 고급 - 입력 (Input) 프로그래밍/WPF2016. 10. 15. 18:56

Input


https://msdn.microsoft.com/ko-kr/library/ms751593(v=vs.110).aspx




Input Overview


https://msdn.microsoft.com/en-us/library/ms754010(v=vs.110).aspx


The Windows Presentation Foundation (WPF) subsystem provides a powerful API for obtaining input from a variety of devices, including the mouse, keyboard, touch, and stylus. This topic describes the services provided by WPF and explains the architecture of the input systems.

Input API

The primary input API exposure is found on the base element classes: UIElementContentElementFrameworkElement, and FrameworkContentElement. For more information about the base elements, see Base Elements Overview. These classes provide functionality for input events related to key presses, mouse buttons, mouse wheel, mouse movement, focus management, and mouse capture, to name a few. By placing the input API on the base elements, rather than treating all input events as a service, the input architecture enables the input events to be sourced by a particular object in the UI, and to support an event routing scheme whereby more than one element has an opportunity to handle an input event. Many input events have a pair of events associated with them. For example, the key down event is associated with the KeyDown and PreviewKeyDown events. The difference in these events is in how they are routed to the target element. Preview events tunnel down the element tree from the root element to the target element. Bubbling events bubble up from the target element to the root element. Event routing in WPF is discussed in more detail later in this overview and in the Routed Events Overview.

Keyboard and Mouse Classes

In addition to the input API on the base element classes, the Keyboard class and Mouse classes provide additional API for working with keyboard and mouse input.

Examples of input API on the Keyboard class are the Modifiers property, which returns the ModifierKeys currently pressed, and the IsKeyDown method, which determines whether a specified key is pressed.

The following example uses the GetKeyStates method to determine if a Key is in the down state.

// Uses the Keyboard.GetKeyStates to determine if a key is down.
// A bitwise AND operation is used in the comparison. 
// e is an instance of KeyEventArgs.
if ((Keyboard.GetKeyStates(Key.Return) & KeyStates.Down) > 0)
{
    btnNone.Background = Brushes.Red;
}

Examples of input API on the Mouse class are MiddleButton, which obtains the state of the middle mouse button, and DirectlyOver, which gets the element the mouse pointer is currently over.

The following example determines whether the LeftButton on the mouse is in the Pressed state.

if (Mouse.LeftButton == MouseButtonState.Pressed)
{
    UpdateSampleResults("Left Button Pressed");
}

The Mouse and Keyboard classes are covered in more detail throughout this overview.

Stylus Input

WPF has integrated support for the Stylus. The Stylus is a pen input made popular by the Tablet PC. WPF applications can treat the stylus as a mouse by using the mouse API, but WPF also exposes a stylus device abstraction that use a model similar to the keyboard and mouse. All stylus-related APIs contain the word "Stylus".

Because the stylus can act as a mouse, applications that support only mouse input can still obtain some level of stylus support automatically. When the stylus is used in such a manner, the application is given the opportunity to handle the appropriate stylus event and then handles the corresponding mouse event. In addition, higher-level services such as ink input are also available through the stylus device abstraction. For more information about ink as input, see Getting Started with Ink.

Event Routing

FrameworkElement can contain other elements as child elements in its content model, forming a tree of elements. In WPF, the parent element can participate in input directed to its child elements or other descendants by handing events. This is especially useful for building controls out of smaller controls, a process known as "control composition" or "compositing." For more information about element trees and how element trees relate to event routes, see Trees in WPF.

Event routing is the process of forwarding events to multiple elements, so that a particular object or element along the route can choose to offer a significant response (through handling) to an event that might have been sourced by a different element. Routed events use one of three routing mechanisms: direct, bubbling, and tunneling. In direct routing, the source element is the only element notified, and the event is not routed to any other elements. However, the direct routed event still offers some additional capabilities that are only present for routed events as opposed to standard CLR events. Bubbling works up the element tree by first notifying the element that sourced the event, then the parent element, and so on. Tunneling starts at the root of the element tree and works down, ending with the original source element. For more information about routed events, see Routed Events Overview.

WPF input events generally come in pairs that consists of a tunneling event and a bubbling event. Tunneling events are distinguished from bubbling events with the "Preview" prefix. For instance, PreviewMouseMove is the tunneling version of a mouse move event and MouseMove is the bubbling version of this event. This event pairing is a convention that is implemented at the element level and is not an inherent capability of the WPF event system. For details, see the WPF Input Events section in Routed Events Overview.

Handling Input Events

To receive input on an element, an event handler must be associated with that particular event. In XAML this is straightforward: you reference the name of the event as an attribute of the element that will be listening for this event. Then, you set the value of the attribute to the name of the event handler that you define, based on a delegate. The event handler must be written in code such as C# and can be included in a code-behind file.

Keyboard events occur when the operating system reports key actions that occur while keyboard focus is on an element. Mouse and stylus events each fall into two categories: events that report changes in pointer position relative to the element, and events that report changes in the state of device buttons.

Keyboard Input Event Example

The following example listens for a left arrow key press. A StackPanel is created that has a Button. An event handler to listen for the left arrow key press is attached to the Button instance.

The first section of the example creates the StackPanel and the Button and attaches the event handler for the KeyDown.

<StackPanel>
  <Button Background="AliceBlue"
          KeyDown="OnButtonKeyDown"
          Content="Button1"/>
</StackPanel>
// Create the UI elements.
StackPanel keyboardStackPanel = new StackPanel();
Button keyboardButton1 = new Button();

// Set properties on Buttons.
keyboardButton1.Background = Brushes.AliceBlue;
keyboardButton1.Content = "Button 1";

// Attach Buttons to StackPanel.
keyboardStackPanel.Children.Add(keyboardButton1);

// Attach event handler.
keyboardButton1.KeyDown += new KeyEventHandler(OnButtonKeyDown);

The second section is written in code and defines the event handler. When the left arrow key is pressed and the Button has keyboard focus, the handler runs and the Background color of the Button is changed. If the key is pressed, but it is not the left arrow key, the Background color of the Button is changed back to its starting color.

private void OnButtonKeyDown(object sender, KeyEventArgs e)
{
    Button source = e.Source as Button;
    if (source != null)
    {
        if (e.Key == Key.Left)
        {
            source.Background = Brushes.LemonChiffon;
        }
        else
        {
            source.Background = Brushes.AliceBlue;
        }
    }
}

Mouse Input Event Example

In the following example, the Background color of a Button is changed when the mouse pointer enters the Button. The Background color is restored when the mouse leaves the Button.

The first section of the example creates the StackPanel and the Button control and attaches the event handlers for the MouseEnter and MouseLeave events to the Button.

<StackPanel>
  <Button Background="AliceBlue"
          MouseEnter="OnMouseExampleMouseEnter"
          MouseLeave="OnMosueExampleMouseLeave">Button

  </Button>
</StackPanel>
// Create the UI elements.
StackPanel mouseMoveStackPanel = new StackPanel();
Button mouseMoveButton = new Button();

// Set properties on Button.
mouseMoveButton.Background = Brushes.AliceBlue;
mouseMoveButton.Content = "Button";

// Attach Buttons to StackPanel.
mouseMoveStackPanel.Children.Add(mouseMoveButton);

// Attach event handler.
mouseMoveButton.MouseEnter += new MouseEventHandler(OnMouseExampleMouseEnter);
mouseMoveButton.MouseLeave += new MouseEventHandler(OnMosueExampleMouseLeave);

The second section of the example is written in code and defines the event handlers. When the mouse enters the Button, the Background color of the Button is changed to SlateGray. When the mouse leaves the Button, the Background color of the Button is changed back to AliceBlue.

private void OnMouseExampleMouseEnter(object sender, MouseEventArgs e)
{
    // Cast the source of the event to a Button.
    Button source = e.Source as Button;

    // If source is a Button.
    if (source != null)
    {
        source.Background = Brushes.SlateGray;
    }
}
private void OnMosueExampleMouseLeave(object sender, MouseEventArgs e)
{
    // Cast the source of the event to a Button.
    Button source = e.Source as Button;

    // If source is a Button.
    if (source != null)
    {
        source.Background = Brushes.AliceBlue;
    }
}

Text Input

The TextInput event enables you to listen for text input in a device-independent manner. The keyboard is the primary means of text input, but speech, handwriting, and other input devices can generate text input also.

For keyboard input, WPF first sends the appropriate KeyDown/KeyUp events. If those events are not handled and the key is textual (rather than a control key such as directional arrows or function keys), then a TextInput event is raised. There is not always a simple one-to-one mapping between KeyDown/KeyUp and TextInput events because multiple keystrokes can generate a single character of text input and single keystrokes can generate multi-character strings. This is especially true for languages such as Chinese, Japanese, and Korean which use Input Method Editors (IMEs) to generate the thousands of possible characters in their corresponding alphabets.

When WPF sends a KeyUp/KeyDown event, Key is set to Key.System if the keystrokes could become part of a TextInput event (if ALT+S is pressed, for example). This allows code in a KeyDown event handler to check for Key.System and, if found, leave processing for the handler of the subsequently raised TextInput event. In these cases, the various properties of the TextCompositionEventArgs argument can be used to determine the original keystrokes. Similarly, if an IME is active, Key has the value of Key.ImeProcessed, and ImeProcessedKey gives the original keystroke or keystrokes.

The following example defines a handler for the Click event and a handler for the KeyDown event.

The first segment of code or markup creates the user interface.

<StackPanel KeyDown="OnTextInputKeyDown">
  <Button Click="OnTextInputButtonClick"
          Content="Open" />
  <TextBox> . . . </TextBox>
</StackPanel>
// Create the UI elements.
StackPanel textInputStackPanel = new StackPanel();
Button textInputeButton = new Button();
TextBox textInputTextBox = new TextBox();
textInputeButton.Content = "Open";

// Attach elements to StackPanel.
textInputStackPanel.Children.Add(textInputeButton);
textInputStackPanel.Children.Add(textInputTextBox);

// Attach event handlers.
textInputStackPanel.KeyDown += new KeyEventHandler(OnTextInputKeyDown);
textInputeButton.Click += new RoutedEventHandler(OnTextInputButtonClick);

The second segment of code contains the event handlers.

private void OnTextInputKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.O && Keyboard.Modifiers == ModifierKeys.Control)
    {
        handle();
        e.Handled = true;
    }
}

private void OnTextInputButtonClick(object sender, RoutedEventArgs e)
{
    handle();
    e.Handled = true;
} 

public void handle()
{
    MessageBox.Show("Pretend this opens a file");
}

Because input events bubble up the event route, the StackPanel receives the input regardless of which element has keyboard focus. The TextBoxcontrol is notified first and the OnTextInputKeyDown handler is called only if the TextBox did not handle the input. If the PreviewKeyDown event is used instead of the KeyDown event, the OnTextInputKeyDown handler is called first.

In this example, the handling logic is written two times—one time for CTRL+O, and again for button's click event. This can be simplified by using commands, instead of handling the input events directly. Commands are discussed in this overview and in Commanding Overview.

Touch and Manipulation

New hardware and API in the Windows 7 operating system provide applications the ability to receive input from multiple touches simultaneously. WPF enables applications to detect and respond to touch in a manner similar to responding to other input, such as the mouse or keyboard, by raising events when touch occurs.

WPF exposes two types of events when touch occurs: touch events and manipulation events. Touch events provide raw data about each finger on a touchscreen and its movement. Manipulation events interpret the input as certain actions. Both types of events are discussed in this section.

Prerequisites

You need the following components to develop an application that responds to touch.

  • Microsoft Visual Studio 2010.

  • Windows 7.

  • A device, such as a touchscreen, that supports Windows Touch.

Terminology

The following terms are used when touch is discussed.

  • Touch is a type of user input that is recognized by Windows 7. Usually, touch is initiated by putting fingers on a touch-sensitive screen. Note that devices such as a touchpad that is common on laptop computers do not support touch if the device merely converts the finger's position and movement as mouse input.

  • Multitouch is touch that occurs from more than one point simultaneously. Windows 7 and WPF supports multitouch. Whenever touch is discussed in the documentation for WPF, the concepts apply to multitouch.

  • manipulation occurs when touch is interpreted as a physical action that is applied to an object. In WPF, manipulation events interpret input as a translation, expansion, or rotation manipulation.

  • touch device represents a device that produces touch input, such as a single finger on a touchscreen.

  

Controls that Respond to Touch

The following controls can be scrolled by dragging a finger across the control if it has content that is scrolled out of view.

The ScrollViewer defines the ScrollViewer.PanningMode attached property that enables you to specify whether touch panning is enabled horizontally, vertically, both, or neither. The ScrollViewer.PanningDeceleration property specifies how quickly the scrolling slows down when the user lifts the finger from the touchscreen. The ScrollViewer.PanningRatio attached property specifies the ratio of scrolling offset to translate manipulation offset.

Touch Events

The base classes, UIElementUIElement3D, and ContentElement, define events that you can subscribe to so your application will respond to touch. Touch events are useful when your application interprets touch as something other than manipulating an object. For example, an application that enables a user to draw with one or more fingers would subscribe to touch events.

All three classes define the following events, which behave similarly, regardless of the defining class.

Like keyboard and mouse events, the touch events are routed events. The events that begin with Preview are tunneling events and the events that begin with Touch are bubbling events. For more information about routed events, see Routed Events Overview. When you handle these events, you can get the position of the input, relative to any element, by calling the GetTouchPoint or GetIntermediateTouchPoints method.

To understand the interaction among the touch events, consider the scenario where a user puts one finger on an element, moves the finger in the element, and then lifts the finger from the element. The following illustration shows the execution of the bubbling events (the tunneling events are omitted for simplicity).

The sequence of touch events.

Touch events

The following list describes the sequence of the events in the preceding illustration.

  1. The TouchEnter event occurs one time when the user puts a finger on the element.

  2. The TouchDown event occurs one time.

  3. The TouchMove event occurs multiple times as the user moves the finger within the element.

  4. The TouchUp event occurs one time when the user lifts the finger from the element.

  5. The TouchLeave event occurs one time.

When more than two fingers are used, the events occur for each finger.

Manipulation Events

For cases where an application enables a user to manipulate an object, the UIElement class defines manipulation events. Unlike the touch events that simply report the position of touch, the manipulation events report how the input can be interpreted. There are three types of manipulations, translation, expansion, and rotation. The following list describes how to invoke the three types of manipulations.

  • Put a finger on an object and move the finger across the touchscreen to invoke a translation manipulation. This usually moves the object.

  • Put two fingers on an object and move the fingers closer together or farther apart from one another to invoke an expansion manipulation. This usually resizes the object.

  • Put two fingers on an object and rotate the fingers around each other to invoke a rotation manipulation. This usually rotates the object.

More than one type of manipulation can occur simultaneously.

When you cause objects to respond to manipulations, you can have the object appear to have inertia. This can make your objects simulate the physical world. For example, when you push a book across a table, if you push hard enough the book will continue to move after you release it. WPF enables you to simulate this behavior by raising manipulation events after the user's fingers releases the object.

For information about how to create an application that enables the user to move, resize, and rotate an object, see Walkthrough: Creating Your First Touch Application.

The UIElement defines the following manipulation events.

By default, a UIElement does not receive these manipulation events. To receive manipulation events on a UIElement, set UIElement.IsManipulationEnabled to true.

The Execution Path of Manipulation Events

Consider a scenario where a user "throws" an object. The user puts a finger on the object, moves the finger across the touchscreen for a short distance, and then lifts the finger while it is moving. The result of this is that the object will move under the user's finger and continue to move after the user lifts the finger.

The following illustration shows the execution path of manipulation events and important information about each event.

The sequence of manipulation events.

Manipulation events

The following list describes the sequence of the events in the preceding illustration.

  1. The ManipulationStarting event occurs when the user places a finger on the object. Among other things, this event allows you to set the ManipulationContainer property. In the subsequent events, the position of the manipulation will be relative to the ManipulationContainer. In events other than ManipulationStarting, this property is read-only, so the ManipulationStarting event is the only time that you can set this property.

  2. The ManipulationStarted event occurs next. This event reports the origin of the manipulation.

  3. The ManipulationDelta event occurs multiple times as a user's fingers move on a touchscreen. The DeltaManipulation property of the ManipulationDeltaEventArgs class reports whether the manipulation is interpreted as movement, expansion, or translation. This is where you perform most of the work of manipulating an object.

  4. The ManipulationInertiaStarting event occurs when the user's fingers lose contact with the object. This event enables you to specify the deceleration of the manipulations during inertia. This is so your object can emulate different physical spaces or attributes if you choose. For example, suppose your application has two objects that represent items in the physical world, and one is heavier than the other. You can make the heavier object decelerate faster than the lighter object.

  5. The ManipulationDelta event occurs multiple times as inertia occurs. Note that this event occurs when the user's fingers move across the touchscreen and when WPF simulates inertia. In other words, ManipulationDelta occurs before and after the ManipulationInertiaStartingevent. The ManipulationDeltaEventArgs.IsInertial property reports whether the ManipulationDelta event occurs during inertia, so you can check that property and perform different actions, depending on its value.

  6. The ManipulationCompleted event occurs when the manipulation and any inertia ends. That is, after all the ManipulationDelta events occur, the ManipulationCompleted event occurs to signal that the manipulation is complete.

The UIElement also defines the ManipulationBoundaryFeedback event. This event occurs when the ReportBoundaryFeedback method is called in the ManipulationDelta event. The ManipulationBoundaryFeedback event enables applications or components to provide visual feedback when an object hits a boundary. For example, the Window class handles the ManipulationBoundaryFeedback event to cause the window to slightly move when its edge is encountered.

You can cancel the manipulation by calling the Cancel method on the event arguments in any manipulation event except ManipulationBoundaryFeedback event. When you call Cancel, the manipulation events are no longer raised and mouse events occur for touch. The following table describes the relationship between the time the manipulation is canceled and the mouse events that occur.

The event that Cancel is called in

The mouse events that occur for input that already occurred

ManipulationStarting and ManipulationStarted

Mouse down events.

ManipulationDelta

Mouse down and mouse move events.

ManipulationInertiaStarting and ManipulationCompleted 

Mouse down, mouse move, and mouse up events.

Note that if you call Cancel when the manipulation is in inertia, the method returns false and the input does not raise mouse events.

The Relationship Between Touch and Manipulation Events

UIElement can always receive touch events. When the IsManipulationEnabled property is set to true, a UIElement can receive both touch and manipulation events. If the TouchDown event is not handled (that is, the Handled property is false), the manipulation logic captures the touch to the element and generates the manipulation events. If the Handled property is set to true in the TouchDown event, the manipulation logic does not generate manipulation events. The following illustration shows the relationship between touch events and manipulation events.

Relationship between touch and manipulation events

Touch and manipulation events

The following list describes the relationship between the touch and manipulation events that is shown in the preceding illustration.

Focus

There are two main concepts that pertain to focus in WPF: keyboard focus and logical focus.

Keyboard Focus

Keyboard focus refers to the element that is receiving keyboard input. There can be only one element on the whole desktop that has keyboard focus. In WPF, the element that has keyboard focus will have IsKeyboardFocused set to true. The static Keyboard method FocusedElement returns the element that currently has keyboard focus.

Keyboard focus can be obtained by tabbing to an element or by clicking the mouse on certain elements, such as a TextBox. Keyboard focus can also be obtained programmatically by using the Focus method on the Keyboard class. Focus attempts to give the specified element keyboard focus. The element returned by Focus is the element that currently has keyboard focus.

In order for an element to obtain keyboard focus the Focusable property and the IsVisible properties must be set to true. Some classes, such as Panel, have Focusable set to false by default; therefore, you may have to set this property to true if you want that element to be able to obtain focus.

The following example uses Focus to set keyboard focus on a Button. The recommended place to set initial focus in an application is in the Loadedevent handler.

private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}

For more information about keyboard focus, see Focus Overview.

Logical Focus

Logical focus refers to the FocusManager.FocusedElement in a focus scope. There can be multiple elements that have logical focus in an application, but there may only be one element that has logical focus in a particular focus scope.

A focus scope is a container element that keeps track of the FocusedElement within its scope. When focus leaves a focus scope, the focused element will lose keyboard focus but will retain logical focus. When focus returns to the focus scope, the focused element will obtain keyboard focus. This allows for keyboard focus to be changed between multiple focus scopes but insures that the focused element within the focus scope remains the focused element when focus returns.

An element can be turned into a focus scope in Extensible Application Markup Language (XAML) by setting the FocusManager attached property IsFocusScope to true, or in code by setting the attached property by using the SetIsFocusScope method.

The following example makes a StackPanel into a focus scope by setting the IsFocusScope attached property.

<StackPanel Name="focusScope1" 
            FocusManager.IsFocusScope="True"
            Height="200" Width="200">
  <Button Name="button1" Height="50" Width="50"/>
  <Button Name="button2" Height="50" Width="50"/>
</StackPanel>
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);

Classes in WPF which are focus scopes by default are WindowMenuToolBar, and ContextMenu.

An element that has keyboard focus will also have logical focus for the focus scope it belongs to; therefore, setting focus on an element with the Focus method on the Keyboard class or the base element classes will attempt to give the element keyboard focus and logical focus.

To determine the focused element in a focus scope, use GetFocusedElement. To change the focused element for a focus scope, use SetFocusedElement.

For more information about logical focus, see Focus Overview.

Mouse Position

The WPF input API provides helpful information with regard to coordinate spaces. For example, coordinate (0,0) is the upper-left coordinate, but the upper-left of which element in the tree? The element that is the input target? The element you attached your event handler to? Or something else? To avoid confusion, the WPF input API requires that you specify your frame of reference when you work with coordinates obtained through the mouse. The GetPosition method returns the coordinate of the mouse pointer relative to the specified element.

Mouse Capture

Mouse devices specifically hold a modal characteristic known as mouse capture. Mouse capture is used to maintain a transitional input state when a drag-and-drop operation is started, so that other operations involving the nominal on-screen position of the mouse pointer do not necessarily occur. During the drag, the user cannot click without aborting the drag-and-drop, which makes most mouseover cues inappropriate while the mouse capture is held by the drag origin. The input system exposes APIs that can determine mouse capture state, as well as APIs that can force mouse capture to a specific element, or clear mouse capture state. For more information on drag-and-drop operations, see Drag and Drop Overview.

Commands

Commands enable input handling at a more semantic level than device input. Commands are simple directives, such as CutCopyPaste, or Open. Commands are useful for centralizing your command logic. The same command might be accessed from a Menu, on a ToolBar, or through a keyboard shortcut. Commands also provide a mechanism for disabling controls when the command becomes unavailable.

RoutedCommand is the WPF implementation of ICommand. When a RoutedCommand is executed, a PreviewExecuted and an Executed event are raised on the command target, which tunnel and bubble through the element tree like other input. If a command target is not set, the element with keyboard focus will be the command target. The logic that performs the command is attached to a CommandBinding. When an Executed event reaches a CommandBinding for that specific command, the ExecutedRoutedEventHandler on the CommandBinding is called. This handler performs the action of the command.

For more information on commanding, see Commanding Overview.

WPF provides a library of common commands which consists of ApplicationCommandsMediaCommandsComponentCommandsNavigationCommands, and EditingCommands, or you can define your own.

The following example shows how to set up a MenuItem so that when it is clicked it will invoke the Paste command on the TextBox, assuming the TextBox has keyboard focus.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste" />
  </Menu>
  <TextBox />
</StackPanel>
// Creating the UI objects
StackPanel mainStackPanel = new StackPanel();
TextBox pasteTextBox = new TextBox();
Menu stackPanelMenu = new Menu();
MenuItem pasteMenuItem = new MenuItem();

// Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem);
mainStackPanel.Children.Add(stackPanelMenu);
mainStackPanel.Children.Add(pasteTextBox);

// Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste;

// Setting the command target to the TextBox
pasteMenuItem.CommandTarget = pasteTextBox;

For more information about commands in WPF, see Commanding Overview.

The Input System and Base Elements

Input events such as the attached events defined by the MouseKeyboard, and Stylus classes are raised by the input system and injected into a particular position in the object model based on hit testing the visual tree at run time.

Each of the events that MouseKeyboard, and Stylus define as an attached event is also re-exposed by the base element classes UIElement and ContentElement as a new routed event. The base element routed events are generated by classes handling the original attached event and reusing the event data.

When the input event becomes associated with a particular source element through its base element input event implementation, it can be routed through the remainder of an event route that is based on a combination of logical and visual tree objects, and be handled by application code. Generally, it is more convenient to handle these device-related input events using the routed events on UIElement and ContentElement, because you can use more intuitive event handler syntax both in XAML and in code. You could choose to handle the attached event that initiated the process instead, but you would face several issues: the attached event may be marked handled by the base element class handling, and you need to use accessor methods rather than true event syntax in order to attach handlers for attached events.

What's Next

You now have several techniques to handle input in WPF. You should also have an improved understanding of the various types of input events and the routed event mechanisms used by WPF.

Additional resources are available that explain WPF framework elements and event routing in more detail. See the following overviews for more information, Commanding OverviewFocus OverviewBase Elements OverviewTrees in WPF, and Routed Events Overview.





Commanding Overview


https://msdn.microsoft.com/en-us/library/ms752308(v=vs.110).aspx



Commanding is an input mechanism in Windows Presentation Foundation (WPF) which provides input handling at a more semantic level than device input. Examples of commands are the CopyCut, and Paste operations found on many applications.

This overview defines what commands are in WPF, which classes are part of the commanding model, and how to use and create commands in your applications.

This topic contains the following sections:

What Are Commands?

Commands have several purposes. The first purpose is to separate the semantics and the object that invokes a command from the logic that executes the command. This allows for multiple and disparate sources to invoke the same command logic, and it allows the command logic to be customized for different targets. For example, the editing operations CopyCut, and Paste, which are found in many applications, can be invoked by using different user actions if they are implemented by using commands. An application might allow a user to cut selected objects or text by either clicking a button, choosing an item in a menu, or using a key combination, such as CTRL+X. By using commands, you can bind each type of user action to the same logic.

Another purpose of commands is to indicate whether an action is available. To continue the example of cutting an object or text, the action only makes sense when something is selected. If a user tries to cut an object or text without having anything selected, nothing would happen. To indicate this to the user, many applications disable buttons and menu items so that the user knows whether it is possible to perform an action. A command can indicate whether an action is possible by implementing the CanExecute method. A button can subscribe to the CanExecuteChanged event and be disabled if CanExecute returns false or be enabled if CanExecute returns true.

The semantics of a command can be consistent across applications and classes, but the logic of the action is specific to the particular object acted upon. The key combination CTRL+X invokes the Cut command in text classes, image classes, and Web browsers, but the actual logic for performing the Cut operation is defined by the application that performs the cut. A RoutedCommand enables clients to implement the logic. A text object may cut the selected text into the clipboard, while an image object may cut the selected image. When an application handles the Executed event, it has access to the target of the command and can take appropriate action depending on the target's type.

Simple Command Example in WPF

The simplest way to use a command in WPF is to use a predefined RoutedCommand from one of the command library classes; use a control that has native support for handling the command; and use a control that has native support for invoking a command. The Paste command is one of the predefined commands in the ApplicationCommands class. The TextBox control has built in logic for handling the Paste command. And the MenuItemclass has native support for invoking commands.

The following example shows how to set up a MenuItem so that when it is clicked it will invoke the Paste command on a TextBox, assuming the TextBox has keyboard focus.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste" />
  </Menu>
  <TextBox />
</StackPanel>
// Creating the UI objects
StackPanel mainStackPanel = new StackPanel();
TextBox pasteTextBox = new TextBox();
Menu stackPanelMenu = new Menu();
MenuItem pasteMenuItem = new MenuItem();

// Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem);
mainStackPanel.Children.Add(stackPanelMenu);
mainStackPanel.Children.Add(pasteTextBox);

// Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste;

// Setting the command target to the TextBox
pasteMenuItem.CommandTarget = pasteTextBox;

Four Main Concepts in WPF Commanding

The routed command model in WPF can be broken up into four main concepts: the command, the command source, the command target, and the command binding:

  • The command is the action to be executed.

  • The command source is the object which invokes the command.

  • The command target is the object that the command is being executed on.

  • The command binding is the object which maps the command logic to the command.

In the previous example, the Paste command is the command, the MenuItem is the command source, the TextBox is the command target, and the command binding is supplied by the TextBox control. It is worth noting that it is not always the case that the CommandBinding is supplied by the control that is the command target class. Quite often the CommandBinding must be created by the application developer, or the CommandBindingmight be attached to an ancestor of the command target.

Commands

Commands in WPF are created by implementing the ICommand interface. ICommand exposes two methods, Execute, and CanExecute, and an event, CanExecuteChangedExecute performs the actions that are associated with the command. CanExecute determines whether the command can execute on the current command target. CanExecuteChanged is raised if the command manager that centralizes the commanding operations detects a change in the command source that might invalidate a command that has been raised but not yet executed by the command binding. The WPF implementation of ICommand is the RoutedCommand class and is the focus of this overview.

The main sources of input in WPF are the mouse, the keyboard, ink, and routed commands. The more device-oriented inputs use a RoutedEvent to notify objects in an application page that an input event has occurred. A RoutedCommand is no different. The Execute and CanExecute methods of a RoutedCommand do not contain the application logic for the command, but rather they raise routed events that tunnel and bubble through the element tree until they encounter an object with a CommandBinding. The CommandBinding contains the handlers for these events and it is the handlers that perform the command. For more information on event routing in WPF, see Routed Events Overview.

The Execute method on a RoutedCommand raises the PreviewExecuted and the Executed events on the command target. The CanExecute method on a RoutedCommand raises the CanExecute and PreviewCanExecute events on the command target. These events tunnel and bubble through the element tree until they encounter an object which has a CommandBinding for that particular command.

WPF supplies a set of common routed commands spread across several classes: MediaCommandsApplicationCommandsNavigationCommandsComponentCommands, and EditingCommands. These classes consist only of the RoutedCommand objects and not the implementation logic of the command. The implementation logic is the responsibility of the object on which the command is being executed on.

Command Sources

A command source is the object which invokes the command. Examples of command sources are MenuItemButton, and KeyGesture.

Command sources in WPF generally implement the ICommandSource interface.

 

ICommandSource exposes three properties: CommandCommandTarget, and CommandParameter:

The WPF classes that implement ICommandSource are ButtonBaseMenuItemHyperlink, and InputBindingButtonBaseMenuItem, and Hyperlinkinvoke a command when they are clicked, and an InputBinding invokes a command when the InputGesture associated with it is performed.

The following example shows how to use a MenuItem in a ContextMenu as a command source for the Properties command.

<StackPanel>
  <StackPanel.ContextMenu>
    <ContextMenu>
      <MenuItem Command="ApplicationCommands.Properties" />
    </ContextMenu>
  </StackPanel.ContextMenu>
</StackPanel>
StackPanel cmdSourcePanel = new StackPanel();
ContextMenu cmdSourceContextMenu = new ContextMenu();
MenuItem cmdSourceMenuItem = new MenuItem();

// Add ContextMenu to the StackPanel.
cmdSourcePanel.ContextMenu = cmdSourceContextMenu;
cmdSourcePanel.ContextMenu.Items.Add(cmdSourceMenuItem);

// Associate Command with MenuItem.
cmdSourceMenuItem.Command = ApplicationCommands.Properties;

Typically, a command source will listen to the CanExecuteChanged event. This event informs the command source that the ability of the command to execute on the current command target may have changed. The command source can query the current status of the RoutedCommand by using the CanExecute method. The command source can then disable itself if the command cannot execute. An example of this is a MenuItemgraying itself out when a command cannot execute.

An InputGesture can be used as a command source. Two types of input gestures in WPF are the KeyGesture and MouseGesture. You can think of a KeyGesture as a keyboard shortcut, such as CTRL+C. A KeyGesture is comprised of a Key and a set of ModifierKeys. A MouseGesture is comprised of a MouseAction and an optional set of ModifierKeys.

In order for an InputGesture to act as a command source, it must be associated with a command. There are a few ways to accomplish this. One way is to use an InputBinding.

The following example shows how to create a KeyBinding between a KeyGesture and a RoutedCommand.

<Window.InputBindings>
  <KeyBinding Key="B"
              Modifiers="Control" 
              Command="ApplicationCommands.Open" />
</Window.InputBindings>
KeyGesture OpenKeyGesture = new KeyGesture(
    Key.B,
    ModifierKeys.Control);

KeyBinding OpenCmdKeybinding = new KeyBinding(
    ApplicationCommands.Open,
    OpenKeyGesture);

this.InputBindings.Add(OpenCmdKeybinding);

Another way to associate an InputGesture to a RoutedCommand is to add the InputGesture to the InputGestureCollection on the RoutedCommand.

The following example shows how to add a KeyGesture to the InputGestureCollection of a RoutedCommand.

KeyGesture OpenCmdKeyGesture = new KeyGesture(
    Key.B,
    ModifierKeys.Control);

ApplicationCommands.Open.InputGestures.Add(OpenCmdKeyGesture);

CommandBinding

CommandBinding associates a command with the event handlers that implement the command.

The CommandBinding class contains a Command property, and PreviewExecutedExecutedPreviewCanExecute, and CanExecute events.

Command is the command that the CommandBinding is being associated with. The event handlers which are attached to the PreviewExecuted and Executed events implement the command logic. The event handlers attached to the PreviewCanExecute and CanExecute events determine if the command can execute on the current command target.

The following example shows how to create a CommandBinding on the root Window of an application. The CommandBinding associates the Opencommand with Executed and CanExecute handlers.

<Window.CommandBindings>
  <CommandBinding Command="ApplicationCommands.Open"
                  Executed="OpenCmdExecuted"
                  CanExecute="OpenCmdCanExecute"/>
</Window.CommandBindings>
// Creating CommandBinding and attaching an Executed and CanExecute handler
CommandBinding OpenCmdBinding = new CommandBinding(
    ApplicationCommands.Open,
    OpenCmdExecuted,
    OpenCmdCanExecute);

this.CommandBindings.Add(OpenCmdBinding);

Next, the ExecutedRoutedEventHandler and a CanExecuteRoutedEventHandler are created. The ExecutedRoutedEventHandler opens a MessageBoxthat displays a string saying the command has been executed. The CanExecuteRoutedEventHandler sets the CanExecute property to true.

void OpenCmdExecuted(object target, ExecutedRoutedEventArgs e)
{
    String command, targetobj;
    command = ((RoutedCommand)e.Command).Name;
    targetobj = ((FrameworkElement)target).Name;
    MessageBox.Show("The " + command +  " command has been invoked on target object " + targetobj);
}
void OpenCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
}

CommandBinding is attached to a specific object, such as the root Window of the application or a control. The object that the CommandBindingis attached to defines the scope of the binding. For example, a CommandBinding attached to an ancestor of the command target can be reached by the Executed event, but a CommandBinding attached to a descendant of the command target cannot be reached. This is a direct consequence of the way a RoutedEvent tunnels and bubbles from the object that raises the event.

In some situations the CommandBinding is attached to the command target itself, such as with the TextBox class and the CutCopy, and Pastecommands. Quite often though, it is more convenient to attach the CommandBinding to an ancestor of the command target, such as the main Window or the Application object, especially if the same CommandBinding can be used for multiple command targets. These are design decisions you will want to consider when you are creating your commanding infrastructure.

Command Target

The command target is the element on which the command is executed. With regards to a RoutedCommand, the command target is the element at which routing of the Executed and CanExecute starts. As noted previously, in WPF the CommandTarget property on ICommandSource is only applicable when the ICommand is a RoutedCommand. If the CommandTarget is set on an ICommandSource and the corresponding command is not a RoutedCommand, the command target is ignored.

The command source can explicitly set the command target. If the command target is not defined, the element with keyboard focus will be used as the command target. One of the benefits of using the element with keyboard focus as the command target is that it allows the application developer to use the same command source to invoke a command on multiple targets without having to keep track of the command target. For example, if a MenuItem invokes the Paste command in an application that has a TextBox control and a PasswordBox control, the target can be either the TextBox or PasswordBox depending on which control has keyboard focus.

The following example shows how to explicitly set the command target in markup and in code behind.

<StackPanel>
  <Menu>
    <MenuItem Command="ApplicationCommands.Paste"
              CommandTarget="{Binding ElementName=mainTextBox}" />
  </Menu>
  <TextBox Name="mainTextBox"/>
</StackPanel>
// Creating the UI objects
StackPanel mainStackPanel = new StackPanel();
TextBox pasteTextBox = new TextBox();
Menu stackPanelMenu = new Menu();
MenuItem pasteMenuItem = new MenuItem();

// Adding objects to the panel and the menu
stackPanelMenu.Items.Add(pasteMenuItem);
mainStackPanel.Children.Add(stackPanelMenu);
mainStackPanel.Children.Add(pasteTextBox);

// Setting the command to the Paste command
pasteMenuItem.Command = ApplicationCommands.Paste;

// Setting the command target to the TextBox
pasteMenuItem.CommandTarget = pasteTextBox;

The CommandManager

The CommandManager serves a number of command related functions. It provides a set of static methods for adding and removing PreviewExecutedExecutedPreviewCanExecute, and CanExecute event handlers to and from a specific element. It provides a means to register CommandBinding and InputBinding objects onto a specific class. The CommandManager also provides a means, through the RequerySuggestedevent, to notify a command when it should raise the CanExecuteChanged event.

The InvalidateRequerySuggested method forces the CommandManager to raise the RequerySuggested event. This is useful for conditions that should disable/enable a command but are not conditions that the CommandManager is aware of.

Command Library

WPF provides a set of predefined commands. The command library consists of the following classes: ApplicationCommandsNavigationCommandsMediaCommandsEditingCommands, and the ComponentCommands. These classes provide commands such as CutBrowseBack and BrowseForwardPlayStop, and Pause.

Many of these commands include a set of default input bindings. For example, if you specify that your application handles the copy command, you automatically get the keyboard binding "CTRL+C" You also get bindings for other input devices, such as Tablet PC pen gestures and speech information.

When you reference commands in the various command libraries using XAML, you can usually omit the class name of the library class that exposes the static command property. Generally, the command names are unambiguous as strings, and the owning types exist to provide a logical grouping of commands but are not necessary for disambiguation. For instance, you can specify Command="Cut" rather than the more verbose Command="ApplicationCommands.Cut". This is a convenience mechanism that is built in to the WPF XAML processor for commands (more precisely, it is a type converter behavior of ICommand, which the WPF XAML processor references at load time).

Creating Custom Commands

If the commands in the command library classes do not meet your needs, then you can create your own commands. There are two ways to create a custom command. The first is to start from the ground up and implement the ICommand interface. The other way, and the more common approach, is to create a RoutedCommand or a RoutedUICommand.

For an example of creating a custom RoutedCommand, see Create a Custom RoutedCommand Sample.






Focus Overview


https://msdn.microsoft.com/en-us/library/aa969768(v=vs.110).aspx


In WPF there are two main concepts that pertain to focus: keyboard focus and logical focus. Keyboard focus refers to the element that receives keyboard input and logical focus refers to the element in a focus scope that has focus. These concepts are discussed in detail in this overview. Understanding the difference in these concepts is important for creating complex applications that have multiple regions where focus can be obtained.

The major classes that participate in focus management are the Keyboard class, the FocusManager class, and the base element classes, such as UIElement and ContentElement. For more information about the base elements, see the Base Elements Overview.

The Keyboard class is concerned primarily with keyboard focus and the FocusManager is concerned primarily with logical focus, but this is not an absolute distinction. An element that has keyboard focus will also have logical focus, but an element that has logical focus does not necessarily have keyboard focus. This is apparent when you use the Keyboard class to set the element that has keyboard focus, for it also sets logical focus on the element.

Keyboard Focus

Keyboard focus refers to the element that is currently receiving keyboard input. There can be only one element on the whole desktop that has keyboard focus. In WPF, the element that has keyboard focus will have IsKeyboardFocused set to true. The static property FocusedElement on the Keyboard class gets the element that currently has keyboard focus. 

In order for an element to obtain keyboard focus, the Focusable and the IsVisible properties on the base elements must be set to true. Some classes, such as the Panel base class, have Focusable set to false by default; therefore, you must set Focusable to true if you want such an element to be able to obtain keyboard focus.

Keyboard focus can be obtained through user interaction with the UI, such as tabbing to an element or clicking the mouse on certain elements. Keyboard focus can also be obtained programmatically by using the Focus method on the Keyboard class. The Focus method attempts to give the specified element keyboard focus. The returned element is the element that has keyboard focus, which might be a different element than requested if either the old or new focus object block the request. 

The following example uses the Focus method to set keyboard focus on a Button.

private void OnLoaded(object sender, RoutedEventArgs e)
{
    // Sets keyboard focus on the first Button in the sample.
    Keyboard.Focus(firstButton);
}

The IsKeyboardFocused property on the base element classes gets a value indicating whether the element has keyboard focus. The IsKeyboardFocusWithin property on the base element classes gets a value indicating whether the element or any one of its visual child elements has keyboard focus.

When setting initial focus at application startup, the element to receive focus must be in the visual tree of the initial window loaded by the application, and the element must have Focusable and IsVisible set to true. The recommended place to set initial focus is in the Loaded event handler. Dispatcher callback can also be used by calling Invoke or BeginInvoke.

Logical Focus

Logical focus refers to the FocusManager.FocusedElement in a focus scope. A focus scope is an element that keeps track of the FocusedElement within its scope. When keyboard focus leaves a focus scope, the focused element will lose keyboard focus but will retain logical focus. When keyboard focus returns to the focus scope, the focused element will obtain keyboard focus. This allows for keyboard focus to be changed between multiple focus scopes but ensures that the focused element in the focus scope regains keyboard focus when focus returns to the focus scope.

There can be multiple elements that have logical focus in an application, but there may only be one element that has logical focus in a particular focus scope.

An element that has keyboard focus has logical focus for the focus scope it belongs to.

An element can be turned into a focus scope in Extensible Application Markup Language (XAML) by setting the FocusManager attached property IsFocusScope to true. In code, an element can be turned into a focus scope by calling SetIsFocusScope.

The following example makes a StackPanel into a focus scope by setting the IsFocusScope attached property.

<StackPanel Name="focusScope1" 
            FocusManager.IsFocusScope="True"
            Height="200" Width="200">
  <Button Name="button1" Height="50" Width="50"/>
  <Button Name="button2" Height="50" Width="50"/>
</StackPanel>
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);

GetFocusScope returns the focus scope for the specified element.

Classes in WPF which are focus scopes by default are WindowMenuItemToolBar, and ContextMenu.

GetFocusedElement gets the focused element for the specified focus scope. SetFocusedElement sets the focused element in the specified focus scope. SetFocusedElement is typically used to set the initial focused element.

The following example sets the focused element on a focus scope and gets the focused element of a focus scope.

// Sets the focused element in focusScope1
// focusScope1 is a StackPanel.
FocusManager.SetFocusedElement(focusScope1, button2);

// Gets the focused element for focusScope 1
IInputElement focusedElement = FocusManager.GetFocusedElement(focusScope1);

Keyboard Navigation

The KeyboardNavigation class is responsible for implementing default keyboard focus navigation when one of the navigation keys is pressed. The navigation keys are: TAB, SHIFT+TAB, CTRL+TAB, CTRL+SHIFT+TAB, UPARROW, DOWNARROW, LEFTARROW, and RIGHTARROW keys.

The navigation behavior of a navigation container can be changed by setting the attached KeyboardNavigation properties TabNavigationControlTabNavigation, and DirectionalNavigation. These properties are of type KeyboardNavigationMode and the possible values are ContinueLocalContainedCycleOnce, and None. The default value is Continue, which means the element is not a navigation container.

The following example creates a Menu with a number of MenuItem objects. The TabNavigation attached property is set to Cycle on the Menu. When focus is changed using the tab key within the Menu, focus will move from each element and when the last element is reached focus will return to the first element.

<Menu KeyboardNavigation.TabNavigation="Cycle">
  <MenuItem Header="Menu Item 1" />
  <MenuItem Header="Menu Item 2" />
  <MenuItem Header="Menu Item 3" />
  <MenuItem Header="Menu Item 4" />
</Menu>
Menu navigationMenu = new Menu();
MenuItem item1 = new MenuItem();
MenuItem item2 = new MenuItem();
MenuItem item3 = new MenuItem();
MenuItem item4 = new MenuItem();

navigationMenu.Items.Add(item1);
navigationMenu.Items.Add(item2);
navigationMenu.Items.Add(item3);
navigationMenu.Items.Add(item4);

KeyboardNavigation.SetTabNavigation(navigationMenu, 
    KeyboardNavigationMode.Cycle);

Navigating Focus Programmatically

Additional API to work with focus are MoveFocus and PredictFocus.

MoveFocus changes focus to the next element in the application. A TraversalRequest is used to specify the direction. The FocusNavigationDirectionpassed to MoveFocus specifies the different directions focus can be moved, such as FirstLastUp and Down.

The following example uses MoveFocus to change the focused element.

// Creating a FocusNavigationDirection object and setting it to a
// local field that contains the direction selected.
FocusNavigationDirection focusDirection = _focusMoveValue;

// MoveFocus takes a TraveralReqest as its argument.
TraversalRequest request = new TraversalRequest(focusDirection);

// Gets the element with keyboard focus.
UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;

// Change keyboard focus.
if (elementWithFocus != null)
{
    elementWithFocus.MoveFocus(request);
}

PredictFocus returns the object which would receive focus if focus were to be changed. Currently, only UpDownLeft, and Right are supported by PredictFocus.

Focus Events

The events related to keyboard focus are PreviewGotKeyboardFocusGotKeyboardFocus and PreviewLostKeyboardFocusLostKeyboardFocus. The events are defined as attached events on the Keyboard class, but are more readily accessible as equivalent routed events on the base element classes. For more information about events, see the Routed Events Overview.

GotKeyboardFocus is raised when the element obtains keyboard focus. LostKeyboardFocus is raised when the element loses keyboard focus. If the PreviewGotKeyboardFocus event or the PreviewLostKeyboardFocusEvent event is handled and Handled is set to true, then focus will not change.

The following example attaches GotKeyboardFocus and LostKeyboardFocus event handlers to a TextBox.

<Border BorderBrush="Black" BorderThickness="1"
        Width="200" Height="100" Margin="5">
  <StackPanel>
    <Label HorizontalAlignment="Center" Content="Type Text In This TextBox" />
    <TextBox Width="175"
             Height="50" 
             Margin="5"
             TextWrapping="Wrap"
             HorizontalAlignment="Center"
             VerticalScrollBarVisibility="Auto"
             GotKeyboardFocus="TextBoxGotKeyboardFocus"
             LostKeyboardFocus="TextBoxLostKeyboardFocus"
             KeyDown="SourceTextKeyDown"/>
  </StackPanel>
</Border>

When the TextBox obtains keyboard focus, the Background property of the TextBox is changed to LightBlue.

private void TextBoxGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    TextBox source = e.Source as TextBox;

    if (source != null)
    {
        // Change the TextBox color when it obtains focus.
        source.Background = Brushes.LightBlue;

        // Clear the TextBox.
        source.Clear();
    }
}

When the TextBox loses keyboard focus, the Background property of the TextBox is changed back to white.

private void TextBoxLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
    TextBox source = e.Source as TextBox;

    if (source != null)
    {
        // Change the TextBox color when it loses focus.
        source.Background = Brushes.White;

        // Set the  hit counter back to zero and updates the display.
        this.ResetCounter();
    }
} 

The events related to logical focus are GotFocus and LostFocus. These events are defined on the FocusManager as attached events, but the FocusManager does not expose CLR event wrappers. UIElement and ContentElement expose these events more conveniently.



Styling for Focus in Controls, and FocusVisualStyle


Windows Presentation Foundation (WPF) provides two parallel mechanisms for changing the visual appearance of a control when it receives keyboard focus. The first mechanism is to use property setters for properties such as IsKeyboardFocused within the style or template that is applied to the control. The second mechanism is to provide a separate style as the value of the FocusVisualStyle property; the "focus visual style" creates a separate visual tree for an adorner that draws on top of the control, rather than changing the visual tree of the control or other UI element by replacing it. This topic discusses the scenarios where each of these mechanisms is appropriate.

The Purpose of Focus Visual Style

The focus visual style feature provides a common "object model" for introducing visual user feedback based on keyboard navigation to any UI element. This is possible without applying a new template to the control, or knowing the specific template composition.

However, precisely because the focus visual style feature works without knowing the control templates, the visual feedback that can be displayed for a control using a focus visual style is necessarily limited. What the feature actually does is to overlay a different visual tree (an adorner) on top of the visual tree as created by a control's rendering through its template. You define this separate visual tree using a style that fills the FocusVisualStyleproperty.

Default Focus Visual Style Behavior

Focus visual styles act only when the focus action was initiated by the keyboard. Any mouse action or programmatic focus change disables the mode for focus visual styles. For more information about the distinctions between focus modes, see Focus Overview.

The themes for controls include a default focus visual style behavior that becomes the focus visual style for all controls in the theme. This theme style is identified by the value of the static key FocusVisualStyleKey. When you declare your own focus visual style at the application level, you replace this default style behavior from the themes. Alternatively, if you define the entire theme, then you should use this same key to define the style for the default behavior for your entire theme.

In the themes, the default focus visual style is generally very simple. The following is a rough approximation:

<Style x:Key="{x:Static SystemParameters.FocusVisualStyleKey}">
  <Setter Property="Control.Template">
    <Setter.Value>
      <ControlTemplate>
        <Rectangle StrokeThickness="1"
          Stroke="Black"
          StrokeDashArray="1 2"
          SnapsToDevicePixels="true"/>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

When to Use Focus Visual Styles

Conceptually, the appearance of focus visual styles applied to controls should be coherent from control to control. One way to ensure coherence is to change the focus visual style only if you are composing an entire theme, where each control that is defined in the theme gets either the very same focus visual style, or some variation of a style that is visually related from control to control. Alternatively, you might use the same style (or similar styles) to style every keyboard-focusable element on a page or in a UI.

Setting FocusVisualStyle on individual control styles that are not part of a theme is not the intended usage of focus visual styles. This is because an inconsistent visual behavior between controls can lead to a confusing user experience regarding keyboard focus. If you are intending control-specific behaviors for keyboard focus that are deliberately not coherent across a theme, a much better approach is to use triggers in styles for individual input state properties, such as IsFocused or IsKeyboardFocused.

Focus visual styles act exclusively for keyboard focus. As such, focus visual styles are a type of accessibility feature. If you want UI changes for any type of focus, whether via mouse, keyboard, or programmatically, then you should not use focus visual styles, and should instead use setters and triggers in styles or templates that are working from the value of general focus properties such as IsFocused or IsFocusWithin.

How to Create a Focus Visual Style

The style you create for a focus visual style should always have the TargetType of Control. The style should consist mainly of a ControlTemplate. You do not specify the target type to be the type where the focus visual style is assigned to the FocusVisualStyle.

Because the target type is always Control, you must style by using properties that are common to all controls (using properties of the Control class and its base classes). You should create a template that will properly function as an overlay to a UI element and that will not obscure functional areas of the control. Generally, this means that the visual feedback should appear outside the control margins, or as temporary or unobtrusive effects that will not block the hit testing on the control where the focus visual style is applied. Properties that you can use in template binding that are useful for determining sizing and positioning of your overlay template include ActualHeightActualWidthMargin, and Padding.

Alternatives to Using a Focus Visual Style

For situations where using a focus visual style is not appropriate, either because you are only styling single controls or because you want greater control over the control template, there are many other accessible properties and techniques that can create visual behavior in response to changes in focus.

Triggers, setters, and event setters are all discussed in detail in Styling and Templating. Routed event handling is discussed in Routed Events Overview.

IsKeyboardFocused

If you are specifically interested in keyboard focus, the IsKeyboardFocused dependency property can be used for a property Trigger. A property trigger in either a style or template is a more appropriate technique for defining a keyboard focus behavior that is very specifically for a single control, and which might not visually match the keyboard focus behavior for other controls.

Another similar dependency property is IsKeyboardFocusWithin, which might be appropriate to use if you want to visually call out that keyboard focus is somewhere within compositing or within the functional area of the control. For example, you might place an IsKeyboardFocusWithintrigger such that a panel that groups several controls appears differently, even though keyboard focus might more precisely be on an individual element within that panel.

You can also use the events GotKeyboardFocus and LostKeyboardFocus (as well as their Preview equivalents). You can use these events as the basis for an EventSetter, or you can write handlers for the events in code-behind.

If you want all possible causes of changing focus to produce a visual behavior, you should base a setter or trigger on the IsFocused dependency property, or alternatively on the GotFocus or LostFocus events used for an EventSetter.



Walkthrough: Creating Your First Touch Application


WPF enables applications to respond to touch. For example, you can interact with an application by using one or more fingers on a touch-sensitive device, such as a touchscreen This walkthrough creates an application that enables the user to move, resize, or rotate a single object by using touch.

Prerequisites

You need the following components to complete this walkthrough:

  • Microsoft Visual Studio 2010.

  • Windows 7.

  • A device that accepts touch input, such as a touchscreen, that supports Windows Touch.

Additionally, you should have a basic understanding of how to create an application in WPF, especially how to subscribe to and handle an event. For more information, see Walkthrough: My First WPF Desktop Application.

Creating the Application

To create the application

  1. Create a new WPF Application project in Visual Basic or Visual C# named BasicManipulation. For more information, see How to: Create a New WPF Application Project.

  2. Replace the contents of MainWindow.xaml with the following XAML.

    This markup creates a simple application that contains a red Rectangle on a Canvas. The IsManipulationEnabled property of the Rectangle is set to true so that it will receive manipulation events. The application subscribes to the ManipulationStartingManipulationDelta, and ManipulationInertiaStarting events. These events contain the logic to move the Rectangle when the user manipulates it.

    <Window x:Class="BasicManipulation.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="Move, Size, and Rotate the Square"
            WindowState="Maximized"
            ManipulationStarting="Window_ManipulationStarting"
            ManipulationDelta="Window_ManipulationDelta"
            ManipulationInertiaStarting="Window_InertiaStarting">
      <Window.Resources>
    
        <!--The movement, rotation, and size of the Rectangle is 
            specified by its RenderTransform.-->
        <MatrixTransform x:Key="InitialMatrixTransform">
          <MatrixTransform.Matrix>
            <Matrix OffsetX="200" OffsetY="200"/>
          </MatrixTransform.Matrix>
        </MatrixTransform>
    
      </Window.Resources>
    
      <Canvas>
        <Rectangle Fill="Red" Name="manRect"
                     Width="200" Height="200" 
                     RenderTransform="{StaticResource InitialMatrixTransform}"
                     IsManipulationEnabled="true" />
      </Canvas>
    </Window>
    
    
  3. If you are using Visual Basic, in the first line of MainWindow.xaml, replace x:Class="BasicManipulation.MainWindow" with x:Class="MainWindow".

  4. In the MainWindow class, add the following ManipulationStarting event handler.

    The ManipulationStarting event occurs when WPF detects that touch input begins to manipulate an object. The code specifies that the position of the manipulation should be relative to the Window by setting the ManipulationContainer property.

    void Window_ManipulationStarting(object sender, ManipulationStartingEventArgs e)
    {
        e.ManipulationContainer = this;
        e.Handled = true;
    }
    
  5. In the MainWindow class, add the following ManipulationDelta event handler.

    The ManipulationDelta event occurs when the touch input changes position and can occur multiple times during a manipulation. The event can also occur after a finger is raised. For example, if the user drags a finger across a screen, the ManipulationDelta event occurs multiple times as the finger moves. When the user raises a finger from the screen, the ManipulationDelta event keeps occurring to simulate inertia.

    The code applies the DeltaManipulation to the RenderTransform of the Rectangle to move it as the user moves the touch input. It also checks whether the Rectangle is outside the bounds of the Window when the event occurs during inertia. If so, the application calls the ManipulationDeltaEventArgs.Complete method to end the manipulation.

    void Window_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
    {
    
        // Get the Rectangle and its RenderTransform matrix.
        Rectangle rectToMove = e.OriginalSource as Rectangle;
        Matrix rectsMatrix = ((MatrixTransform)rectToMove.RenderTransform).Matrix;
    
        // Rotate the Rectangle.
        rectsMatrix.RotateAt(e.DeltaManipulation.Rotation, 
                             e.ManipulationOrigin.X, 
                             e.ManipulationOrigin.Y);
    
        // Resize the Rectangle.  Keep it square 
        // so use only the X value of Scale.
        rectsMatrix.ScaleAt(e.DeltaManipulation.Scale.X, 
                            e.DeltaManipulation.Scale.X, 
                            e.ManipulationOrigin.X,
                            e.ManipulationOrigin.Y);
    
        // Move the Rectangle.
        rectsMatrix.Translate(e.DeltaManipulation.Translation.X,
                              e.DeltaManipulation.Translation.Y);
    
        // Apply the changes to the Rectangle.
        rectToMove.RenderTransform = new MatrixTransform(rectsMatrix);
    
        Rect containingRect =
            new Rect(((FrameworkElement)e.ManipulationContainer).RenderSize);
    
        Rect shapeBounds =
            rectToMove.RenderTransform.TransformBounds(
                new Rect(rectToMove.RenderSize));
    
        // Check if the rectangle is completely in the window.
        // If it is not and intertia is occuring, stop the manipulation.
        if (e.IsInertial && !containingRect.Contains(shapeBounds))
        {
            e.Complete();
        }
    
    
        e.Handled = true;
    }
    

  6. In the MainWindow class, add the following ManipulationInertiaStarting event handler.

    The ManipulationInertiaStarting event occurs when the user raises all fingers from the screen. The code sets the initial velocity and deceleration for the movement, expansion, and rotation of the rectangle.

    void Window_InertiaStarting(object sender, ManipulationInertiaStartingEventArgs e)
    {
    
        // Decrease the velocity of the Rectangle's movement by 
        // 10 inches per second every second.
        // (10 inches * 96 pixels per inch / 1000ms^2)
        e.TranslationBehavior.DesiredDeceleration = 10.0 * 96.0 / (1000.0 * 1000.0);
    
        // Decrease the velocity of the Rectangle's resizing by 
        // 0.1 inches per second every second.
        // (0.1 inches * 96 pixels per inch / (1000ms^2)
        e.ExpansionBehavior.DesiredDeceleration = 0.1 * 96 / (1000.0 * 1000.0);
    
        // Decrease the velocity of the Rectangle's rotation rate by 
        // 2 rotations per second every second.
        // (2 * 360 degrees / (1000ms^2)
        e.RotationBehavior.DesiredDeceleration = 720 / (1000.0 * 1000.0);
    
        e.Handled = true;
    }
    

  7. Build and run the project.

    You should see a red square appear in the window.

Testing the Application

To test the application, try the following manipulations. Note that you can do more than one of the following at the same time.

  • To move the Rectangle, put a finger on the Rectangle and move the finger across the screen.

  • To resize the Rectangle, put two fingers on the Rectangle and move the fingers closer together or farther apart from each other.

  • To rotate the Rectangle, put two fingers on the Rectangle and rotate the fingers around each other.

To cause inertia, quickly raise your fingers from the screen as you perform the previous manipulations. The Rectangle will continue to move, resize, or rotate for a few seconds before it stops.



Input and Commands How-to Topics


The following example demonstrates how to use commanding in Windows Presentation Foundation (WPF). The example shows how to associate a RoutedCommand to a Button, create a CommandBinding, and create the event handlers which implement the RoutedCommand. For more information on commanding, see the Commanding Overview.

Example

The first section of code creates the user interface (UI), which consists of a Button and a StackPanel, and creates a CommandBinding that associates the command handlers with the RoutedCommand.

The Command property of the Button is associated with the Close command.

The CommandBinding is added to the CommandBindingCollection of the root Window. The Executed and CanExecute event handlers are attached to this binding and associated with the Close command.

Without the CommandBinding there is no command logic, only a mechanism to invoke the command. When the Button is clicked, the PreviewExecuted RoutedEvent is raised on the command target followed by the Executed RoutedEvent. These events traverse the element tree looking for a CommandBinding for that particular command. It is worth noting that because RoutedEvent tunnel and bubble through the element tree, care must be taken in where the CommandBinding is put. If the CommandBinding is on a sibling of the command target or another node that is not on the route of the RoutedEvent, the CommandBinding will not be accessed.

<Window x:Class="WCSamples.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="CloseCommand"
    Name="RootWindow"
    >
  <Window.CommandBindings>
    <CommandBinding Command="ApplicationCommands.Close"
                    Executed="CloseCommandHandler"
                    CanExecute="CanExecuteHandler"
                    />
  </Window.CommandBindings>
  <StackPanel Name="MainStackPanel">
    <Button Command="ApplicationCommands.Close" 
            Content="Close File" />
  </StackPanel>
</Window>
// Create ui elements.
StackPanel CloseCmdStackPanel = new StackPanel();
Button CloseCmdButton = new Button();
CloseCmdStackPanel.Children.Add(CloseCmdButton);

// Set Button's properties.
CloseCmdButton.Content = "Close File";
CloseCmdButton.Command = ApplicationCommands.Close;

// Create the CommandBinding.
CommandBinding CloseCommandBinding = new CommandBinding(
    ApplicationCommands.Close, CloseCommandHandler, CanExecuteHandler);

// Add the CommandBinding to the root Window.
RootWindow.CommandBindings.Add(CloseCommandBinding);

The next section of code implements the Executed and CanExecute event handlers.

The Executed handler calls a method to close the open file. The CanExecute handler calls a method to determine whether a file is open. If a file is open, CanExecute is set to true; otherwise, it is set to false.

// Executed event handler.
private void CloseCommandHandler(object sender, ExecutedRoutedEventArgs e)
{
    // Calls a method to close the file and release resources.
    CloseFile();
}

// CanExecute event handler.
private void CanExecuteHandler(object sender, CanExecuteRoutedEventArgs e)
{
    // Call a method to determine if there is a file open.
    // If there is a file open, then set CanExecute to true.
    if (IsFileOpened())
    {
        e.CanExecute = true;
    }
    // if there is not a file open, then set CanExecute to false.
    else
    {
        e.CanExecute = false;
    }
}



How to: Change the Cursor Type


This example shows how to change the Cursor of the mouse pointer for a specific element and for the application.

This example consists of a Extensible Application Markup Language (XAML) file and a code behind file.

Example

The user interface is created, which consists of a ComboBox to select the desired Cursor, a pair of RadioButton objects to determine if the cursor change applies to only a single element or applies to the entire application, and a Border which is the element that the new cursor is applied to.

<StackPanel>
  <Border Width="300">
    <StackPanel Orientation="Horizontal"
                HorizontalAlignment="Center">
      <StackPanel Margin="10">
        <Label HorizontalAlignment="Left">Cursor Type</Label>
        <ComboBox Width="100"
                  SelectionChanged="CursorTypeChanged"
                  HorizontalAlignment="Left"
                  Name="CursorSelector">
          <ComboBoxItem Content="AppStarting" />
          <ComboBoxItem Content="ArrowCD" />
          <ComboBoxItem Content="Arrow" />
          <ComboBoxItem Content="Cross" />
          <ComboBoxItem Content="HandCursor" />
          <ComboBoxItem Content="Help" />
          <ComboBoxItem Content="IBeam" />
          <ComboBoxItem Content="No" />
          <ComboBoxItem Content="None" />
          <ComboBoxItem Content="Pen" />
          <ComboBoxItem Content="ScrollSE" />
          <ComboBoxItem Content="ScrollWE" />
          <ComboBoxItem Content="SizeAll" />
          <ComboBoxItem Content="SizeNESW" />
          <ComboBoxItem Content="SizeNS" />
          <ComboBoxItem Content="SizeNWSE" />
          <ComboBoxItem Content="SizeWE" />
          <ComboBoxItem Content="UpArrow" />
          <ComboBoxItem Content="WaitCursor" />
          <ComboBoxItem Content="Custom" />
        </ComboBox>
      </StackPanel>
      <!-- The user can select different cursor types using this ComboBox -->
      <StackPanel Margin="10">
        <Label HorizontalAlignment="Left">Scope of Cursor</Label>
        <StackPanel>
          <RadioButton Name="rbScopeElement" IsChecked="True"
                       Checked="CursorScopeSelected">Display Area Only</RadioButton>
          <RadioButton Name="rbScopeApplication"
                       Checked="CursorScopeSelected">Entire Appliation</RadioButton>
        </StackPanel>
      </StackPanel>
    </StackPanel>
  </Border>
  <!-- When the mouse pointer is over this Border -->
  <!-- the selected cursor type is shown -->
  <Border Name="DisplayArea" Height="250" Width="400"
          Margin="20" Background="AliceBlue">
    <Label HorizontalAlignment="Center">
      Move Mouse Pointer Over This Area
    </Label>
  </Border>
</StackPanel>

The following code behind creates a SelectionChanged event handler which is called when the cursor type is changed in the ComboBox. A switch statement filters on the cursor name and sets the Cursor property on the Border which is named DisplayArea.

If the cursor change is set to "Entire Application", the OverrideCursor property is set to the Cursor property of the Border control. This forces the cursor to change for the whole application.

private void CursorTypeChanged(object sender, SelectionChangedEventArgs e)
{
    ComboBox source = e.Source as ComboBox;

    if (source != null)
    {
        ComboBoxItem selectedCursor = source.SelectedItem as ComboBoxItem;

        // Changing the cursor of the Border control 
        // by setting the Cursor property
        switch (selectedCursor.Content.ToString())
        {
            case "AppStarting":
                DisplayArea.Cursor = Cursors.AppStarting;
                break;
            case "ArrowCD":                        
                DisplayArea.Cursor = Cursors.ArrowCD;
                break;
            case "Arrow":
                DisplayArea.Cursor = Cursors.Arrow;
                break;
            case "Cross":
                DisplayArea.Cursor = Cursors.Cross;
                break;
            case "HandCursor":
                DisplayArea.Cursor = Cursors.Hand;
                break;
            case "Help":
                DisplayArea.Cursor = Cursors.Help;
                break;
            case "IBeam":
                DisplayArea.Cursor = Cursors.IBeam;
                break;
            case "No":
                DisplayArea.Cursor = Cursors.No;
                break;
            case "None":
                DisplayArea.Cursor = Cursors.None;
                break;
            case "Pen":
                DisplayArea.Cursor = Cursors.Pen;
                break;
            case "ScrollSE":
                DisplayArea.Cursor = Cursors.ScrollSE;
                break;
            case "ScrollWE":
                DisplayArea.Cursor = Cursors.ScrollWE;
                break;
            case "SizeAll":
                DisplayArea.Cursor = Cursors.SizeAll;
                break;
            case "SizeNESW":
                DisplayArea.Cursor = Cursors.SizeNESW;
                break;
            case "SizeNS":
                DisplayArea.Cursor = Cursors.SizeNS;
                break;
            case "SizeNWSE":
                DisplayArea.Cursor = Cursors.SizeNWSE;
                break;
            case "SizeWE":
                DisplayArea.Cursor = Cursors.SizeWE;
                break;
            case "UpArrow":
                DisplayArea.Cursor = Cursors.UpArrow;
                break;
            case "WaitCursor":
                DisplayArea.Cursor = Cursors.Wait;
                break;
            case "Custom":
                DisplayArea.Cursor = CustomCursor;
                break;
            default:
                break;
        }

        // If the cursor scope is set to the entire application
        // Use OverrideCursor to force the cursor for all elements
        if (cursorScopeElementOnly == false)
        {
            Mouse.OverrideCursor = DisplayArea.Cursor;
        }
    }
}





How to: Change the Color of an Element Using Focus Events

https://msdn.microsoft.com/en-us/library/ms749310(v=vs.110).aspx

This example shows how to change the color of an element when it gains and loses focus by using the GotFocus and LostFocus events.

This example consists of a Extensible Application Markup Language (XAML) file and a code-behind file.

Example

The following XAML creates the user interface, which consists of two Button objects, and attaches event handlers for the GotFocus and LostFocus events to the Button objects.

<StackPanel>
  <StackPanel.Resources>
    <Style TargetType="{x:Type Button}">
      <Setter Property="Height" Value="20"/>
      <Setter Property="Width" Value="250"/>
      <Setter Property="HorizontalAlignment" Value="Left"/>
    </Style>
  </StackPanel.Resources>
  <Button
      GotFocus="OnGotFocusHandler"
      LostFocus="OnLostFocusHandler">Click Or Tab To Give Keyboard Focus</Button>
  <Button
      GotFocus="OnGotFocusHandler"
      LostFocus="OnLostFocusHandler">Click Or Tab To Give Keyborad Focus</Button>
</StackPanel>

The following code behind creates the GotFocus and LostFocus event handlers. When the Button gains keyboard focus, the Background of the Button is changed to red. When the Button loses keyboard focus, the Background of the Button is changed back to white.

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    // Raised when Button gains focus.
    // Changes the color of the Button to Red.
    private void OnGotFocusHandler(object sender, RoutedEventArgs e)
    {
        Button tb = e.Source as Button;
        tb.Background = Brushes.Red;
    }
    // Raised when Button losses focus. 
    // Changes the color of the Button back to white.
    private void OnLostFocusHandler(object sender, RoutedEventArgs e)
    {
        Button tb = e.Source as Button;
        tb.Background = Brushes.White;
    }
}




How to: Apply a FocusVisualStyle to a Control


This example shows you how to create a focus visual style in resources and apply the style to a control, using the FocusVisualStyle property.

Example

The following example defines a style that creates additional control compositing that only applies when that control is keyboard focused in the user interface (UI). This is accomplished by defining a style with a ControlTemplate, then referencing that style as a resource when setting the FocusVisualStyle property.

An external rectangle resembling a border is placed outside of the rectangular area. Unless otherwise modified, the sizing of the style uses the ActualHeight and ActualWidth of the rectangular control where the focus visual style is applied. This example sets negative values for the Margin to make the border appear slightly outside the focused control.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
  <Page.Resources>
    <Style x:Key="MyFocusVisual">
      <Setter Property="Control.Template">
        <Setter.Value>
          <ControlTemplate>
            <Rectangle Margin="-2" StrokeThickness="1" Stroke="Red" StrokeDashArray="1 2"/>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>
  </Page.Resources>
  <StackPanel Background="Ivory" Orientation="Horizontal">
    <Canvas Width="10"/>
    <Button Width="100" Height="30" FocusVisualStyle="{DynamicResource MyFocusVisual}">
      Focus Here</Button>
    <Canvas Width="100"/>
    <Button Width="100" Height="30" FocusVisualStyle="{DynamicResource MyFocusVisual}">
      Focus Here</Button>
  </StackPanel>
</Page>

FocusVisualStyle is additive to any control template style that comes either from an explicit style or a theme style; the primary style for a control can still be created by using a ControlTemplate and setting that style to the Style property.

Focus visual styles should be used consistently across a theme or a UI, rather than using a different one for each focusable element. For details, see Styling for Focus in Controls, and FocusVisualStyle.




How to: Detect When the Enter Key Pressed


This example shows how to detect when the Enter key is pressed on the keyboard.

This example consists of a Extensible Application Markup Language (XAML) file and a code-behind file.

Example

When the user presses the Enter key in the TextBox, the input in the text box appears in another area of the user interface (UI).

The following XAML creates the user interface, which consists of a StackPanel, a TextBlock, and a TextBox.

<StackPanel>
  <TextBlock Width="300" Height="20">
    Type some text into the TextBox and press the Enter key.
  </TextBlock>
  <TextBox Width="300" Height="30" Name="textBox1"
           KeyDown="OnKeyDownHandler"/>
  <TextBlock Width="300" Height="100" Name="textBlock1"/>
</StackPanel>

The following code behind creates the KeyDown event handler. If the key that is pressed is the Enter key, a message is displayed in the TextBlock.

private void OnKeyDownHandler(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Return)
    {
        textBlock1.Text = "You Entered: " + textBox1.Text;
    }
}




How to: Create a Rollover Effect Using Events


This example shows how to change the color of an element as the mouse pointer enters and leaves the area occupied by the element.

This example consists of a Extensible Application Markup Language (XAML) file and a code-behind file.

System_CAPS_noteNote

This example demonstrates how to use events, but the recommended way to achieve this same effect is to use a Trigger in a style. For more information, see Styling and Templating.

Example

The following XAML creates the user interface, which consists of Border around a TextBlock, and attaches the MouseEnter and MouseLeave event handlers to the Border.

<StackPanel>
  <Border MouseEnter="OnMouseEnterHandler"
          MouseLeave="OnMouseLeaveHandler"
          Name="border1" Margin="10"
          BorderThickness="1"
          BorderBrush="Black"
          VerticalAlignment="Center"
          Width="300" Height="100">
    <Label Margin="10" FontSize="14"
           HorizontalAlignment="Center">Move Cursor Over Me</Label>
  </Border>
</StackPanel>

The following code behind creates the MouseEnter and MouseLeave event handlers. When the mouse pointer enters the Border, the background of the Border is changed to red. When the mouse pointer leaves the Border, the background of the Border is changed back to white.

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    // raised when mouse cursor enters the area occupied by the element
    void OnMouseEnterHandler(object sender, MouseEventArgs e)
    {
        border1.Background = Brushes.Red;
    }

    // raised when mouse cursor leaves the area occupied by the element
    void OnMouseLeaveHandler(object sender, MouseEventArgs e)
    {
        border1.Background = Brushes.White;
    }
}




How to: Make an Object Follow the Mouse Pointer


This example shows how to change the dimensions of an object when the mouse pointer moves on the screen.

The example includes an Extensible Application Markup Language (XAML) file that creates the user interface (UI) and a code-behind file that creates the event handler.

Example

The following XAML creates the UI, which consists of an Ellipse inside of a StackPanel, and attaches the event handler for the MouseMove event.

<Window x:Class="WCSamples.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="mouseMoveWithPointer"
    Height="400"
    Width="500"
    >
  <Canvas MouseMove="MouseMoveHandler"
          Background="LemonChiffon">
    <Ellipse Name="ellipse" Fill="LightBlue" 
             Width="100" Height="100"/>
  </Canvas>
</Window>

The following code behind creates the MouseMove event handler. When the mouse pointer moves, the height and the width of the Ellipse are increased and decreased.

// raised when the mouse pointer moves.
// Expands the dimensions of an Ellipse when the mouse moves.
private void MouseMoveHandler(object sender, MouseEventArgs e)
{
    // Get the x and y coordinates of the mouse pointer.
    System.Windows.Point position = e.GetPosition(this);
    double pX = position.X;
    double pY = position.Y;

    // Sets the Height/Width of the circle to the mouse coordinates.
    ellipse.Width = pX;
    ellipse.Height = pY;
}





How to: Create a RoutedCommand


This example shows how to create a custom RoutedCommand and how to implement the custom command by creating a ExecutedRoutedEventHandlerand a CanExecuteRoutedEventHandler and attaching them to a CommandBinding. For more information on commanding, see the Commanding Overview.

Example

The first step in creating a RoutedCommand is defining the command and instantiating it.

public static RoutedCommand CustomRoutedCommand = new RoutedCommand();

In order to use the command in an application, event handlers which define what the command does must be created

private void ExecutedCustomCommand(object sender,
    ExecutedRoutedEventArgs e)
{
    MessageBox.Show("Custom Command Executed");
}
// CanExecuteRoutedEventHandler that only returns true if
// the source is a control.
private void CanExecuteCustomCommand(object sender, 
    CanExecuteRoutedEventArgs e)
{
    Control target = e.Source as Control;

    if(target != null)
    {
        e.CanExecute = true;
    }
    else
    {
        e.CanExecute = false;
    }
}

Next, a CommandBinding is created which associates the command with the event handlers. The CommandBinding is created on a specific object. This object defines the scope of the CommandBinding in the element tree

<Window x:Class="SDKSamples.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:custom="clr-namespace:SDKSamples"
    Height="600" Width="800"
    >
  <Window.CommandBindings>
    <CommandBinding Command="{x:Static custom:Window1.CustomRoutedCommand}"
                    Executed="ExecutedCustomCommand"
                    CanExecute="CanExecuteCustomCommand" />
  </Window.CommandBindings>
CommandBinding customCommandBinding = new CommandBinding(
    CustomRoutedCommand, ExecutedCustomCommand, CanExecuteCustomCommand);

// attach CommandBinding to root window
this.CommandBindings.Add(customCommandBinding);

The final step is invoking the command. One way to invoke a command is to associate it with a ICommandSource, such as a Button.

<StackPanel>
  <Button Command="{x:Static custom:Window1.CustomRoutedCommand}"
          Content="CustomRoutedCommand"/>
</StackPanel>
// create the ui
StackPanel CustomCommandStackPanel = new StackPanel();
Button CustomCommandButton = new Button();
CustomCommandStackPanel.Children.Add(CustomCommandButton);

CustomCommandButton.Command = CustomRoutedCommand; 

When the Button is clicked, the Execute method on the custom RoutedCommand is called. The RoutedCommand raises the PreviewExecuted and Executed routed events. These events traverse the element tree looking for a CommandBinding for this particular command. If a CommandBinding is found, the ExecutedRoutedEventHandler associated with CommandBinding is called.


<Code-behind>

public static RoutedCommand CustomRoutedCommand = new RoutedCommand();


private void ExecutedCustomCommand(object sender,

    ExecutedRoutedEventArgs e)

        {

            MessageBox.Show("Custom Command Executed");

        }


private void CanExecuteCustomCommand(object sender,

    CanExecuteRoutedEventArgs e)

        {

            Control target = e.Source as Control;


            if (target != null)

            {

                e.CanExecute = true;

            }

            else

            {

                e.CanExecute = false;

            }

        }


private void Window_Loaded(object sender, RoutedEventArgs e)

        {

            CommandBinding customCommandBinding = new CommandBinding(CustomRoutedCommand, ExecutedCustomCommand, CanExecuteCustomCommand);


            CommandBindings.Add(customCommandBinding);


            StackPanel CustomCommandStackPanel = new StackPanel();

            Button CustomCommandButton = new Button();

            CustomCommandButton.Content = "버튼";

            CustomCommandStackPanel.Children.Add(CustomCommandButton);


            CustomCommandButton.Command = CustomRoutedCommand;


            Content = CustomCommandStackPanel;

        }


<XAML>

<Window.CommandBindings>

        <CommandBinding Command="{x:Static local:Window1.CustomRoutedCommand}"

                    Executed="ExecutedCustomCommand"

                    CanExecute="CanExecuteCustomCommand" />

    </Window.CommandBindings>

    <StackPanel>

        <Button Command="{x:Static local:Window1.CustomRoutedCommand}" Content="CustomRoutedCommand"/>

    </StackPanel>


public static RoutedCommand CustomRoutedCommand = new RoutedCommand();


        private void ExecutedCustomCommand(object sender,

    ExecutedRoutedEventArgs e)

        {

            MessageBox.Show("Custom Command Executed");

        }


        private void CanExecuteCustomCommand(object sender,

    CanExecuteRoutedEventArgs e)

        {

            Control target = e.Source as Control;            


            if (target != null)

            {

                e.CanExecute = true;

            }

            else

            {

                e.CanExecute = false;

            }

        }




How to: Implement ICommandSource


This example shows how to create a command source by implementing ICommandSource. A command source is an object that knows how to invoke a command. The ICommandSource interface exposes three members: Command, CommandParameter, and CommandTarget. Command is the command which will be invoked. The CommandParameter is a user-defined data type which is passed from the command source to the method which handles the command. The CommandTarget is the object that the command is being executed on.

In this example, a class is created which subclasses the Slider control and implements ICommandSource.

Example

WPF provides a number of classes which implement ICommandSource, such as ButtonMenuItem, and ListBoxItem. A command source defines how it invokes a command. Button and MenuItem invoke a command when they are clicked. A ListBoxItem invokes a command when it is double clicked. These classes only become a command source when their Command property is set.

For this example we will invoke the command when the slider is moved, or more accurately, when the Value property is changed.

The following is the class definition.

public class CommandSlider : Slider, ICommandSource
{
    public CommandSlider() : base()
    {

    }

The next step is to implement the ICommandSource members. In this example, the properties are implemented as DependencyProperty objects. This enables the properties to use data binding. For more information about the DependencyProperty class, see the Dependency Properties Overview. For more information about data binding, see the Data Binding Overview.

Only the Command property is shown here.

// Make Command a dependency property so it can use databinding.
public static readonly DependencyProperty CommandProperty =
    DependencyProperty.Register(
        "Command",
        typeof(ICommand),
        typeof(CommandSlider),
        new PropertyMetadata((ICommand)null,
        new PropertyChangedCallback(CommandChanged)));

public ICommand Command
{
    get 
    {
        return (ICommand)GetValue(CommandProperty);
    }
    set 
    {
        SetValue(CommandProperty, value);
    }
}

The following is the DependencyProperty change callback.

// Command dependency property change callback.
private static void CommandChanged(DependencyObject d,
    DependencyPropertyChangedEventArgs e)
{
    CommandSlider cs = (CommandSlider)d;
    cs.HookUpCommand((ICommand)e.OldValue,(ICommand)e.NewValue);
}

The next step is to add and remove the command which is associated with the command source. The Command property cannot simply be overwritten when a new command is added, because the event handlers associated with the previous command, if there was one, must be removed first.

// Add a new command to the Command Property.
private void HookUpCommand(ICommand oldCommand, ICommand newCommand)
{
    // If oldCommand is not null, then we need to remove the handlers.
    if (oldCommand != null)
    {
        RemoveCommand(oldCommand, newCommand);
    }
    AddCommand(oldCommand, newCommand);
}

// Remove an old command from the Command Property.
private void RemoveCommand(ICommand oldCommand, ICommand newCommand)
{
    EventHandler handler = CanExecuteChanged;
    oldCommand.CanExecuteChanged -= handler;
}

// Add the command.
private void AddCommand(ICommand oldCommand, ICommand newCommand)
{
    EventHandler handler = new EventHandler(CanExecuteChanged);
    canExecuteChangedHandler = handler;
    if (newCommand != null)
    {
        newCommand.CanExecuteChanged += canExecuteChangedHandler;
    }
}

The last step is to create logic for the CanExecuteChanged handler and the Execute method.

The CanExecuteChanged event notifies the command source that the ability of the command to execute on the current command target may have changed. When a command source receives this event, it typically calls the CanExecute method on the command. If the command cannot execute on the current command target, the command source will typically disable itself. If the command can execute on the current command target, the command source will typically enable itself.

private void CanExecuteChanged(object sender, EventArgs e)
{

    if (this.Command != null)
    {
        RoutedCommand command = this.Command as RoutedCommand;

        // If a RoutedCommand.
        if (command != null)
        {
            if (command.CanExecute(CommandParameter, CommandTarget))
            {
                this.IsEnabled = true;
            }
            else
            {
                this.IsEnabled = false;
            }
        }
        // If a not RoutedCommand.
        else
        {
            if (Command.CanExecute(CommandParameter))
            {
                this.IsEnabled = true;
            }
            else
            {
                this.IsEnabled = false;
            }
        }
    }
}

The last step is the Execute method. If the command is a RoutedCommand, the RoutedCommand Execute method is called; otherwise, the ICommand Execute method is called.

// If Command is defined, moving the slider will invoke the command;
// Otherwise, the slider will behave normally.
protected override void OnValueChanged(double oldValue, double newValue)
{
    base.OnValueChanged(oldValue, newValue);

    if (this.Command != null)
    {
        RoutedCommand command = Command as RoutedCommand;

        if (command != null)
        {
            command.Execute(CommandParameter, CommandTarget);
        }
        else
        {
            ((ICommand)Command).Execute(CommandParameter);
        }
    }
}




How to: Hook Up a Command to a Control with No Command Support


The following example shows how to hook up a RoutedCommand to a Control which does not have built in support for the command. For a complete sample which hooks up commands to multiple sources, see the Create a Custom RoutedCommand Sample sample.

Example

Windows Presentation Foundation (WPF) provides a library of common commands which application programmers encounter regularly. The classes which comprise the command library are: ApplicationCommandsComponentCommandsNavigationCommandsMediaCommands, and EditingCommands.

The static RoutedCommand objects which make up these classes do not supply command logic. The logic for the command is associated with the command with a CommandBinding. Many controls in WPF have built in support for some of the commands in the command library. TextBox, for example, supports many of the application edit commands such as PasteCopyCutRedo, and Undo. The application developer does not have to do anything special to get these commands to work with these controls. If the TextBox is the command target when the command is executed, it will handle the command using the CommandBinding that is built into the control.

The following shows how to use a Button as the command source for the Open command. A CommandBinding is created that associates the specified CanExecuteRoutedEventHandler and the CanExecuteRoutedEventHandler with the RoutedCommand.

First, the command source is created. A Button is used as the command source.

<Button Command="ApplicationCommands.Open" Name="MyButton"
        Height="50" Width="200">
  Open (KeyBindings: Ctrl+R, Ctrl+0)
</Button>
// Button used to invoke the command
Button CommandButton = new Button();
CommandButton.Command = ApplicationCommands.Open;
CommandButton.Content = "Open (KeyBindings: Ctrl-R, Ctrl-0)";
MainStackPanel.Children.Add(CommandButton);

Next, the ExecutedRoutedEventHandler and the CanExecuteRoutedEventHandler are created. The ExecutedRoutedEventHandler simply opens a MessageBox to signify that the command executed. The CanExecuteRoutedEventHandler sets the CanExecute property to true. Normally, the can execute handler would perform more robust checks to see if the command could execute on the current command target.

void OpenCmdExecuted(object target, ExecutedRoutedEventArgs e)
{
    String command, targetobj;
    command = ((RoutedCommand)e.Command).Name;
    targetobj = ((FrameworkElement)target).Name;
    MessageBox.Show("The " + command +  " command has been invoked on target object " + targetobj);
}
void OpenCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
}

Finally, a CommandBinding is created on the root Window of the application that associates the routed events handlers to the Open command.

<Window.CommandBindings>
  <CommandBinding Command="ApplicationCommands.Open"
                  Executed="OpenCmdExecuted"
                  CanExecute="OpenCmdCanExecute"/>
</Window.CommandBindings>
// Creating CommandBinding and attaching an Executed and CanExecute handler
CommandBinding OpenCmdBinding = new CommandBinding(
    ApplicationCommands.Open,
    OpenCmdExecuted,
    OpenCmdCanExecute);

this.CommandBindings.Add(OpenCmdBinding);




How to: Hook Up a Command to a Control with Command Support


The following example shows how to hook up a RoutedCommand to a Control which has built in support for the command. For a complete sample which hooks up commands to multiple sources, see the Create a Custom RoutedCommand Sample sample.

Example

Windows Presentation Foundation (WPF) provides a library of common commands which application programmers encounter regularly. The classes which comprise the command library are: ApplicationCommandsComponentCommandsNavigationCommandsMediaCommands, and EditingCommands.

The static RoutedCommand objects which make up these classes do not supply command logic. The logic for the command is associated with the command with a CommandBinding. Some controls have built in CommandBindings for some commands. This mechanism allows the semantics of a command to stay the same, while the actual implementation is can change. A TextBox, for example, handles the Paste command differently than a control designed to support images, but the basic idea of what it means to paste something stays the same. The command logic cannot be supplied by the command, but rather must be supplied by the control or the application.

Many controls in WPF do have built in support for some of the commands in the command library. TextBox, for example, supports many of the application edit commands such as PasteCopyCutRedo, and Undo. The application developer does not have to do anything special to get these commands to work with these controls. If the TextBox is the command target when the command is executed, it will handle the command using the CommandBinding that is built into the control.

The following shows how to use a MenuItem as the command source for the Paste command, where a TextBox is the target of the command. All the logic that defines how the TextBox performs the paste is built into the TextBox control.

MenuItem is created and it's Command property is set to the Paste command. The CommandTarget is not explicitly set to the TextBox object. When the CommandTarget is not set, the target for the command is the element which has keyboard focus. If the element which has keyboard focus does not support the Paste command or cannot currently execute the paste command (the clipboard is empty, for example) then the MenuItem would be grayed out.

<Window x:Class="SDKSamples.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MenuItemCommandTask"
    >
    <DockPanel>
      <Menu DockPanel.Dock="Top">
        <MenuItem Command="ApplicationCommands.Paste" Width="75" />
      </Menu>
      <TextBox BorderBrush="Black" BorderThickness="2" Margin="25"
               TextWrapping="Wrap">
        The MenuItem will not be enabled until
        this TextBox gets keyboard focus  
      </TextBox>
    </DockPanel>
</Window>
// Window1 constructor
public Window1()
{
    InitializeComponent();

    // Instantiating UIElements.
    DockPanel mainPanel = new DockPanel();
    Menu mainMenu = new Menu();
    MenuItem pasteMenuItem = new MenuItem();
    TextBox mainTextBox = new TextBox();

    // Associating the MenuItem with the Paste command.
    pasteMenuItem.Command = ApplicationCommands.Paste;

    // Setting properties on the TextBox.
    mainTextBox.Text =
        "The MenuItem will not be enabled until this TextBox receives keyboard focus.";
    mainTextBox.Margin = new Thickness(25);
    mainTextBox.BorderBrush = Brushes.Black;
    mainTextBox.BorderThickness = new Thickness(2);
    mainTextBox.TextWrapping = TextWrapping.Wrap;

    // Attaching UIElements to the Window.
    this.AddChild(mainPanel);
    mainMenu.Items.Add(pasteMenuItem);
    mainPanel.Children.Add(mainMenu);
    mainPanel.Children.Add(mainTextBox);

    // Defining DockPanel layout.
    DockPanel.SetDock(mainMenu, Dock.Top);
    DockPanel.SetDock(mainTextBox, Dock.Bottom);
}







:
Posted by 지훈2