<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ning Zhang&#039;s Blog &#187; WPF</title>
	<atom:link href="http://www.ningzhang.org/category/wpf-msfttech-tech/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.ningzhang.org</link>
	<description>About Silverlight, Microsoft technologies, and software development in general.</description>
	<lastBuildDate>Thu, 14 Apr 2011 22:47:00 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Touch Support in WPF</title>
		<link>http://www.ningzhang.org/2010/10/08/touch-support-in-wpf/</link>
		<comments>http://www.ningzhang.org/2010/10/08/touch-support-in-wpf/#comments</comments>
		<pubDate>Fri, 08 Oct 2010 08:41:10 +0000</pubDate>
		<dc:creator>Ning Zhang</dc:creator>
				<category><![CDATA[WPF]]></category>
		<category><![CDATA[Manipulation]]></category>
		<category><![CDATA[Touch]]></category>

		<guid isPermaLink="false">http://www.ningzhang.org/2010/10/08/touch-support-in-wpf/</guid>
		<description><![CDATA[This post is a slight modification of Touch and Manipulation on MSDN, as a quick overview and reference for myself on WPF touch support. Overview 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 [...]]]></description>
			<content:encoded><![CDATA[<p>This post is a slight modification of <a href="http://msdn.microsoft.com/en-us/library/ms754010.aspx#touch_and_manipulation" target="_blank">Touch and Manipulation</a> on MSDN, as a quick overview and reference for myself on WPF touch support.</p>
<h4>Overview</h4>
<p>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.</p>
<p>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.</p>
<h5>Prerequisites</h5>
<p>You need the following components to develop an application that responds to touch.</p>
<ul>
<li>Microsoft Visual Studio 2010. </li>
<li>Windows 7. </li>
<li>A device, such as a touchscreen, that supports Windows Touch. </li>
</ul>
<p>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.</p>
<h5>Terminology</h5>
<p>The following terms are used when touch is discussed.</p>
<ul>
<li>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&#8217;s position and movement as mouse input. </li>
<li>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. </li>
<li>A 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. </li>
<li>A touch device represents a device that produces touch input, such as a single finger on a touchscreen. </li>
</ul>
<h5>Controls that Respond to Touch</h5>
<p>The following controls can be scrolled by dragging a finger across the control if it has content that is scrolled out of view.</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.combobox.aspx">ComboBox</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.contextmenu.aspx">ContextMenu</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.aspx">DataGrid</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.listbox.aspx">ListBox</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.listview.aspx">ListView</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.menuitem.aspx">MenuItem</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.textbox.aspx">TextBox</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.toolbar.aspx">ToolBar</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.treeview.aspx">TreeView</a> </li>
</ul>
<ul>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.scrollviewer.aspx">ScrollViewer</a> defines the <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.scrollviewer.panningmode.aspx">ScrollViewer.PanningMode</a> attached property that enables you to specify whether touch panning is enabled horizontally, vertically, both, or neither. The <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.scrollviewer.panningdeceleration.aspx">ScrollViewer.PanningDeceleration</a> property specifies how quickly the scrolling slows down when the user lifts the finger from the touchscreen. The <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.scrollviewer.panningratio.aspx">ScrollViewer.PanningRatio</a> attached property specifies the ratio of scrolling offset to translate manipulation offset.</ul>
<ul></ul>
<h5>Class Diagram</h5>
<p>Below class diagram highlights the key classes and their members for touch support:</p>
<p><a href="http://www.ningzhang.org/wp-content/uploads/2010/10/WpfTouchEvents.png" target="_blank"><img style="background-image: none; border-right-width: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="WPF Touch Events Class Diagram" border="0" alt="WPF Touch Events Class Diagram" src="http://www.ningzhang.org/wp-content/uploads/2010/10/WpfTouchEvents_thumb.png" width="604" height="391" /></a></p>
<ul>
<li>Touch
<ul>
<li>Touch events are exposed both by <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a>, <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement3d.aspx">UIElement3D</a>, and <a href="http://msdn.microsoft.com/en-us/library/system.windows.contentelement.aspx">ContentElement</a> as bubbling events, and via <a href="http://msdn.microsoft.com/en-us/library/system.windows.input.touch.aspx" target="_blank">Touch</a>.<a href="http://msdn.microsoft.com/en-us/library/system.windows.input.touch.framereported.aspx" target="_blank">FrameReported</a> as application level event (to be compatible with Silverlight). </li>
<li>While touch down, move and up events are both tunneling and bubbling, touch enter and leave events are bubbling only. </li>
<li>Touch device capture is explicit via <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a>.<a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.capturetouch.aspx" target="_blank">CaptureTouch</a> method. </li>
<li>Touch events are synchronous. </li>
<li>Touch events are always fired, whether manipulation events are fired or not. </li>
<li>WPF supports multitouch. </li>
</ul>
</li>
<li>Manipulation
<ul>
<li>Manipulation events are exposed by <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a> as bubbling event only. </li>
<li>Manipulation events are fired on an <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a> only its <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.ismanipulationenabled.aspx">IsManipulationEnabled</a> is true. </li>
<li>Manipulation events are synchronous. </li>
<li>WPF supports three types of manipulation: expansion and rotation (including single finger rotation with pivot point), and inertia.</li>
<li>Touch device capture is implicit with manipulation. </li>
<li>Static class <a href="http://msdn.microsoft.com/en-us/library/system.windows.input.manipulation.aspx" target="_blank">Manipulation</a> contains methods to get and update manipulation parameters outside of manipulation event handlers. It also contains methods for more advanced usage of manipulation logic, such as adding adding and removing manipulators.&#160; </li>
<li>WPF supports multiple gestures.</li>
<li>WPF doesn’t support gestures, or 3D manipulation.</li>
</ul>
</li>
<li>ScrollViewer has built-in support for manipulation and inertia, and it is customizable by applications. </li>
</ul>
<h4><font face="Verdana">Touch</font></h4>
<h5>Touch Events</h5>
<p>The base classes, <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a>, <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement3d.aspx">UIElement3D</a>, and <a href="http://msdn.microsoft.com/en-us/library/system.windows.contentelement.aspx">ContentElement</a>, 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.</p>
<p>All three classes define the following events, which behave similarly, regardless of the defining class.</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchdown.aspx">TouchDown</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchmove.aspx">TouchMove</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchup.aspx">TouchUp</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchenter.aspx">TouchEnter</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchleave.aspx">TouchLeave</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.previewtouchdown.aspx">PreviewTouchDown</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.previewtouchmove.aspx">PreviewTouchMove</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.previewtouchup.aspx">PreviewTouchUp</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.gottouchcapture.aspx">GotTouchCapture</a> </li>
<li><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.losttouchcapture.aspx">LostTouchCapture</a> </li>
</ul>
<p>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. When you handle these events, you can get the position of the input, relative to any element, by calling the <a href="http://msdn.microsoft.com/en-us/library/system.windows.input.toucheventargs.gettouchpoint.aspx">GetTouchPoint</a> or <a href="http://msdn.microsoft.com/en-us/library/system.windows.input.toucheventargs.getintermediatetouchpoints.aspx">GetIntermediateTouchPoints</a> method.</p>
<h6>The Execution Path of Touch Events</h6>
<p>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).</p>
<p>The following list describes the sequence of the events in the preceding illustration.<img style="margin: 0px 8px 0px 0px; display: inline; float: left" title="The sequence of touch events." alt="The sequence of touch events." align="left" src="http://i.msdn.microsoft.com/dynimg/IC372337.png" /></p>
<ol>
<li>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchenter.aspx">TouchEnter</a> event occurs one time when the user puts a finger on the element.</p>
</li>
<li>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchdown.aspx">TouchDown</a> event occurs one time.</p>
</li>
<li>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchmove.aspx">TouchMove</a> event occurs multiple times as the user moves the finger within the element.</p>
</li>
<li>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchup.aspx">TouchUp</a> event occurs one time when the user lifts the finger from the element.</p>
</li>
<li>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchleave.aspx">TouchLeave</a> event occurs one time.</p>
<p> When more than two fingers are used, the events occur for each finger.</li>
</ol>
<h4>Manipulation and Inertia</h4>
<h5>Manipulation Events</h5>
<p>For cases where an application enables a user to manipulate an object, the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a> 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.</p>
<ul>
<li>
<p>Put a finger on an object and move the finger across the touchscreen to invoke a translation manipulation. This usually moves the object.</p>
</li>
<li>
<p>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.</p>
</li>
<li>
<p>Put two fingers on an object and rotate the fingers around each other to invoke a rotation manipulation. This usually rotates the object.</p>
</li>
</ul>
<p>More than one type of manipulation can occur simultaneously.</p>
<p>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&#8217;s fingers releases the object.</p>
<p>For information about how to create an application that enables the user to move, resize, and rotate an object, see <a href="http://msdn.microsoft.com/en-us/library/ee649090.aspx">Walkthrough: Creating Your First Touch Application</a>.</p>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a> defines the following manipulation events.</p>
<ul>
<li>
<p><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationstarting.aspx">ManipulationStarting</a></p>
</li>
<li>
<p><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationstarted.aspx">ManipulationStarted</a></p>
</li>
<li>
<p><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationdelta.aspx">ManipulationDelta</a></p>
</li>
<li>
<p><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationinertiastarting.aspx">ManipulationInertiaStarting</a></p>
</li>
<li>
<p><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationcompleted.aspx">ManipulationCompleted</a></p>
</li>
<li>
<p><a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationboundaryfeedback.aspx">ManipulationBoundaryFeedback</a></p>
</li>
</ul>
<p>By default, a <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a> does not receive these manipulation events. To receive manipulation events on a <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a>, set <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.ismanipulationenabled.aspx">UIElement.IsManipulationEnabled</a> to true.</p>
<h6>The Execution Path of Manipulation Events</h6>
<p>Consider a scenario where a user &quot;throws&quot; 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&#8217;s finger and continue to move after the user lifts the finger.</p>
<p>The following illustration shows the execution path of manipulation events and important information about each event.</p>
<p>Manipulation events</p>
<p><img style="margin: 0px 8px 0px 0px; display: inline; float: left" title="The sequence of manipulation events." alt="The sequence of manipulation events." align="left" src="http://i.msdn.microsoft.com/dynimg/IC372338.png" /></p>
<p>The following list describes the sequence of the events in the preceding illustration.</p>
<ol>
<li>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationstarting.aspx">ManipulationStarting</a> event occurs when the user places a finger on the object. Among other things, this event allows you to set the <a href="http://msdn.microsoft.com/en-us/library/system.windows.input.manipulationstartingeventargs.manipulationcontainer.aspx">ManipulationContainer</a> property. In the subsequent events, the position of the manipulation will be relative to the <a href="http://msdn.microsoft.com/en-us/library/system.windows.input.manipulationstartingeventargs.manipulationcontainer.aspx">ManipulationContainer</a>. In events other than <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationstarting.aspx">ManipulationStarting</a>, this property is read-only, so the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationstarting.aspx">ManipulationStarting</a> event is the only time that you can set this property.</p>
</li>
<li>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationstarted.aspx">ManipulationStarted</a> event occurs next. This event reports the origin of the manipulation.</p>
</li>
<li>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationdelta.aspx">ManipulationDelta</a> event occurs multiple times as a user&#8217;s fingers move on a touchscreen. The <a href="http://msdn.microsoft.com/en-us/library/system.windows.input.manipulationdeltaeventargs.deltamanipulation.aspx">DeltaManipulation</a> property of the <a href="http://msdn.microsoft.com/en-us/library/system.windows.input.manipulationdeltaeventargs.aspx">ManipulationDeltaEventArgs</a> 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.</p>
</li>
<li>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationinertiastarting.aspx">ManipulationInertiaStarting</a> event occurs when the user&#8217;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.</p>
</li>
<li>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationdelta.aspx">ManipulationDelta</a> event occurs multiple times as inertia occurs. Note that this event occurs when the user&#8217;s fingers move across the touchscreen and when WPF simulates inertia. In other words, <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationdelta.aspx">ManipulationDelta</a> occurs before and after the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationinertiastarting.aspx">ManipulationInertiaStarting</a> event. The <a href="http://msdn.microsoft.com/en-us/library/system.windows.input.manipulationdeltaeventargs.isinertial.aspx">ManipulationDeltaEventArgs.IsInertial</a> property reports whether the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationdelta.aspx">ManipulationDelta</a> event occurs during inertia, so you can check that property and perform different actions, depending on its value.</p>
</li>
<li>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationcompleted.aspx">ManipulationCompleted</a> event occurs when the manipulation and any inertia ends. That is, after all the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationdelta.aspx">ManipulationDelta</a> events occur, the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationcompleted.aspx">ManipulationCompleted</a> event occurs to signal that the manipulation is complete.</p>
</li>
</ol>
<h6>Boundary Feedback</h6>
<p>The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a> also defines the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationboundaryfeedback.aspx">ManipulationBoundaryFeedback</a> event. This event occurs when the <a href="http://msdn.microsoft.com/en-us/library/dd988680.aspx">ReportBoundaryFeedback</a> method is called in the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationdelta.aspx">ManipulationDelta</a> event. The <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationboundaryfeedback.aspx">ManipulationBoundaryFeedback</a> event enables applications or components to provide visual feedback when an object hits a boundary. For example, the <a href="http://msdn.microsoft.com/en-us/library/system.windows.window.aspx">Window</a> class handles the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationboundaryfeedback.aspx">ManipulationBoundaryFeedback</a> event to cause the window to slightly move when its edge is encountered.</p>
<h5>Mouse Promotion</h5>
<p>You can cancel the manipulation by calling the <a href="http://msdn.microsoft.com/en-us/library/ee792639.aspx">Cancel</a> method on the event arguments in any manipulation event except <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationboundaryfeedback.aspx">ManipulationBoundaryFeedback</a> event. When you call <a href="http://msdn.microsoft.com/en-us/library/ee792639.aspx">Cancel</a>, 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.</p>
<p> <span style="text-align: ; widows: 2; text-transform: none; text-indent: 0px; letter-spacing: normal; border-collapse: separate; white-space: normal; orphans: 2; color: ; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px" class="Apple-style-span"><span style="text-align: left; font-family: ; font-size: " class="Apple-style-span"><br />
<table style="border-bottom: rgb(187,187,187) 1px solid; border-left: rgb(187,187,187) 1px solid; background-color: transparent; width: ; border-collapse: collapse; border-top: rgb(187,187,187) 1px solid; border-right: rgb(187,187,187) 1px solid; word-spacing: normal" width="595">
<tbody>
<tr style="vertical-align: top">
<th style="border-bottom: rgb(187,187,187) 1px solid; text-align: ; border-left: rgb(187,187,187) 1px solid; padding-bottom: 4px; background-color: rgb(229,229,229); font-style: ; padding-left: 4px; padding-right: 4px; font-family: ; height: ; color: ; font-size: ; border-top: rgb(187,187,187) 1px solid; font-weight: ; border-right: rgb(187,187,187) 1px solid; padding-top: 4px" height="21" width="167" align="left">
<p><font face="Segoe UI"></font><font style="font-size: " color="#000000" size="2">The event that Cancel is called in</font></p>
</th>
<th style="border-bottom: rgb(187,187,187) 1px solid; text-align: ; border-left: rgb(187,187,187) 1px solid; padding-bottom: 4px; background-color: rgb(229,229,229); font-style: ; padding-left: 4px; padding-right: 4px; font-family: ; height: ; color: ; font-size: ; border-top: rgb(187,187,187) 1px solid; font-weight: ; border-right: rgb(187,187,187) 1px solid; padding-top: 4px" height="21" width="426" align="left">
<p><font face="Segoe UI"></font><font style="font-size: " color="#000000" size="2">The mouse events that occur for input that already occurred</font></p>
</th>
</tr>
<tr style="vertical-align: top">
<td style="border-bottom: rgb(187,187,187) 1px solid; border-left: rgb(187,187,187) 1px solid; padding-bottom: 4px; line-height: 18px; background-color: rgb(255,255,255); margin: 1px; padding-left: 4px; padding-right: 4px; border-top: rgb(187,187,187) 1px solid; border-right: rgb(187,187,187) 1px solid; padding-top: 4px" width="167">
<p><span><a style="color: ; text-decoration: " href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationstarting.aspx"><font color="#1364c4" face="Segoe UI"></font><font style="font-size: " size="2">ManipulationStarting</font></a></span><font face="Segoe UI"></font><font style="font-size: "></font><font color="#000000"></font><font size="2"><span class="Apple-converted-space">&#160;</span>and</font></p>
<p><font face="Segoe UI"><span><a style="color: ; text-decoration: " href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationstarted.aspx"><font style="font-size: " color="#1364c4" size="2">ManipulationStarted</font></a></span></font></p>
</td>
<td style="border-bottom: rgb(187,187,187) 1px solid; border-left: rgb(187,187,187) 1px solid; padding-bottom: 4px; line-height: 18px; background-color: rgb(255,255,255); margin: 1px; padding-left: 4px; padding-right: 4px; border-top: rgb(187,187,187) 1px solid; border-right: rgb(187,187,187) 1px solid; padding-top: 4px" width="426">
<p><font face="Segoe UI"></font><font style="font-size: " color="#000000" size="2">Mouse down events.</font></p>
</td>
</tr>
<tr style="vertical-align: top">
<td style="border-bottom: rgb(187,187,187) 1px solid; border-left: rgb(187,187,187) 1px solid; padding-bottom: 4px; line-height: 18px; background-color: rgb(255,255,255); margin: 1px; padding-left: 4px; padding-right: 4px; border-top: rgb(187,187,187) 1px solid; border-right: rgb(187,187,187) 1px solid; padding-top: 4px" width="167">
<p><span><a style="color: ; text-decoration: " href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationdelta.aspx"><font face="Segoe UI"></font><font style="font-size: " color="#1364c4" size="2">ManipulationDelta</font></a></span></p>
</td>
<td style="border-bottom: rgb(187,187,187) 1px solid; border-left: rgb(187,187,187) 1px solid; padding-bottom: 4px; line-height: 18px; background-color: rgb(255,255,255); margin: 1px; padding-left: 4px; padding-right: 4px; border-top: rgb(187,187,187) 1px solid; border-right: rgb(187,187,187) 1px solid; padding-top: 4px" width="426">
<p><font face="Segoe UI"></font><font style="font-size: " color="#000000" size="2">Mouse down and mouse move events.</font></p>
</td>
</tr>
<tr style="vertical-align: top">
<td style="border-bottom: rgb(187,187,187) 1px solid; border-left: rgb(187,187,187) 1px solid; padding-bottom: 4px; line-height: 18px; background-color: rgb(255,255,255); margin: 1px; padding-left: 4px; padding-right: 4px; border-top: rgb(187,187,187) 1px solid; border-right: rgb(187,187,187) 1px solid; padding-top: 4px" width="167">
<p><span><a style="color: ; text-decoration: " href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationinertiastarting.aspx"><font color="#1364c4" face="Segoe UI"></font><font style="font-size: " size="2">ManipulationInertiaStarting</font></a></span><font face="Segoe UI"></font><font style="font-size: "></font><font color="#000000"></font><font size="2"><span class="Apple-converted-space">&#160;</span>and</font></p>
<p><font face="Segoe UI"><span><a style="color: ; text-decoration: " href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationcompleted.aspx"><font style="font-size: " color="#1364c4" size="2">ManipulationCompleted</font></a></span></font></p>
</td>
<td style="border-bottom: rgb(187,187,187) 1px solid; border-left: rgb(187,187,187) 1px solid; padding-bottom: 4px; line-height: 18px; background-color: rgb(255,255,255); margin: 1px; padding-left: 4px; padding-right: 4px; border-top: rgb(187,187,187) 1px solid; border-right: rgb(187,187,187) 1px solid; padding-top: 4px" width="426">
<p><font face="Segoe UI"></font><font style="font-size: " color="#000000" size="2">Mouse down, mouse move, and mouse up events.</font></p>
</td>
</tr>
</tbody>
</table>
<p>   </span></span>
<p>Note that if you call <a href="http://msdn.microsoft.com/en-us/library/ee792639.aspx">Cancel</a> when the manipulation is in inertia, the method returns false and the input does not raise mouse events.</p>
<h5>The Relationship Between Touch and Manipulation Events</h5>
<p>A <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a> can always receive touch events. When the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.ismanipulationenabled.aspx">IsManipulationEnabled</a> property is set to true, a <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a> can receive both touch and manipulation events. If the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchdown.aspx">TouchDown</a> event is not handled (that is, the <a href="http://msdn.microsoft.com/en-us/library/system.windows.routedeventargs.handled.aspx">Handled</a> property is false), the manipulation logic captures the touch to the element and generates the manipulation events. If the <a href="http://msdn.microsoft.com/en-us/library/system.windows.routedeventargs.handled.aspx">Handled</a> property is set to true in the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchdown.aspx">TouchDown</a> event, the manipulation logic does not generate manipulation events. The following illustration shows the relationship between touch events and manipulation events.</p>
<p>Touch and manipulation events</p>
<p><img title="Relationship between touch and manipulation events" alt="Relationship between touch and manipulation events" src="http://i.msdn.microsoft.com/dynimg/IC392642.png" /></p>
<p>The following list describes the relationship between the touch and manipulation events that is shown in the preceding illustration.</p>
<ul>
<li>
<p>When the first touch device generates a <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchdown.aspx">TouchDown</a> event on a <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.aspx">UIElement</a>, the manipulation logic calls the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.capturetouch.aspx">CaptureTouch</a> method, which generates the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.gottouchcapture.aspx">GotTouchCapture</a> event.</p>
</li>
<li>
<p>When the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.gottouchcapture.aspx">GotTouchCapture</a> occurs, the manipulation logic calls the <a href="http://msdn.microsoft.com/en-us/library/system.windows.input.manipulation.addmanipulator.aspx">Manipulation.AddManipulator</a> method, which generates the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationstarting.aspx">ManipulationStarting</a> event.</p>
</li>
<li>
<p>When the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchmove.aspx">TouchMove</a> events occur, the manipulation logic generates the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationdelta.aspx">ManipulationDelta</a> events that occur before the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationinertiastarting.aspx">ManipulationInertiaStarting</a> event.</p>
</li>
<li>
<p>When the last touch device on the element raises the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.touchup.aspx">TouchUp</a> event, the manipulation logic generates the <a href="http://msdn.microsoft.com/en-us/library/system.windows.uielement.manipulationinertiastarting.aspx">ManipulationInertiaStarting</a> event.</p>
</li>
</ul>
<ul>
<h5>
<ul>EventArgs Class Diagram</ul>
</h5>
<p> Below class diagram shows all the touch and manipulation EventArgs classes and relevant types. </ul>
<ul><a href="http://www.ningzhang.org/wp-content/uploads/2010/10/WpfTouchEventArgs.png" target="_blank"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: ; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="WPF Touch EventArgs Class Diagram" border="0" alt="WPF Touch EventArgs Class Diagram" src="http://www.ningzhang.org/wp-content/uploads/2010/10/WpfTouchEventArgs_thumb.png" width="604" height="310" /></a></ul>
]]></content:encoded>
			<wfw:commentRss>http://www.ningzhang.org/2010/10/08/touch-support-in-wpf/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>DependencyProperty: Validation, Coercion &amp; Change Handling (Part I: WPF)</title>
		<link>http://www.ningzhang.org/2008/11/07/dependencyproperty-validation-coercion-change-handling-part-i-wpf/</link>
		<comments>http://www.ningzhang.org/2008/11/07/dependencyproperty-validation-coercion-change-handling-part-i-wpf/#comments</comments>
		<pubDate>Fri, 07 Nov 2008 08:07:00 +0000</pubDate>
		<dc:creator>Ning Zhang</dc:creator>
				<category><![CDATA[Silverlight]]></category>
		<category><![CDATA[WPF]]></category>
		<category><![CDATA[Dependency Property]]></category>
		<category><![CDATA[NumericUpDown]]></category>
		<category><![CDATA[Silverlight Toolkit]]></category>

		<guid isPermaLink="false">http://nztst.wordpress.com/2008/11/07/dependencyproperty-validation-coercion-change-handling-part-i-wpf/</guid>
		<description><![CDATA[Introduction Dependency property is a major innovation of WPF. A dependency property has the same simple and familiar programming interface as a CLR property, but allows its value to be dynamically decided/changed by many factors, like other properties, styles, templates, data-binding, animation, element composition, class inheritance etc, and can be implemented to provide self-contained default [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>Dependency property is a major innovation of WPF. A dependency property has the same simple and familiar programming interface as a CLR property, but allows its value to be dynamically decided/changed by many factors, like other properties, styles, templates, data-binding, animation, element composition, class inheritance etc, and can be implemented to provide self-contained default value, validation, coercion and eventing logic. Silverlight implements a subset of the WPF property system functions, so there are significant differences between WPF and Silverlight. Straight porting between WPF and Silverlight may not be possible, major source code changes may be required. This three-part post series will use a simple example to demonstrate the common pattern of implementing dependency property on WPF and Silverlight, the difference between the two property systems and how to port from one to another, and then use the NumericUpDown control I wrote for <a href="http://www.codeplex.com/Silverlight" target="_blank">Silverlight Toolkit</a> to demonstrate how complex and tricky dependency property can get on Silverlight. I will only focus on validation, coercion and change handling in this series. When I find time, I may write on other aspects of dependency properties. </p>
<h3>WPF Dependency Property Overview</h3>
<p>MSDN has good <a href="http://msdn.microsoft.com/en-us/library/ms752914.aspx" target="_blank">Dependency Property Overview</a>, so I will just call out the three core classes and two important sets of methods of the programming interface of WPF property system:</p>
<ul>
<li><strong>DependencyProperty</strong>, which provides properties like Name, OwnerType, PropertyType, and methods like Register, RegisterAttached, RegiterReadOnly, RegisterAttachedReadOnly:       <div id="codeSnippetWrapper" class="csharpcode-wrapper">       <pre id="codeSnippet" class="csharpcode">[TypeConverter(<span class="str">&quot;System.Windows.Markup.DependencyPropertyConverter, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Custom=null&quot;</span>), ValueSerializer(<span class="kwrd">typeof</span>(DependencyPropertyValueSerializer))]<br /><span class="kwrd">public</span> <span class="kwrd">sealed</span> <span class="kwrd">class</span> DependencyProperty<br />{<br />    <span class="rem">// Fields</span><br />    <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">readonly</span> <span class="kwrd">object</span> UnsetValue;<br /><br />    <span class="rem">// Methods</span><br />    <span class="kwrd">public</span> DependencyProperty AddOwner(Type ownerType);<br />    <span class="kwrd">public</span> DependencyProperty AddOwner(Type ownerType, PropertyMetadata typeMetadata);<br />    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">int</span> GetHashCode();<br />    <span class="kwrd">public</span> PropertyMetadata GetMetadata(Type forType);<br />    <span class="kwrd">public</span> PropertyMetadata GetMetadata(DependencyObject dependencyObject);<br />    <span class="kwrd">public</span> PropertyMetadata GetMetadata(DependencyObjectType dependencyObjectType);<br />    <span class="kwrd">public</span> <span class="kwrd">bool</span> IsValidType(<span class="kwrd">object</span> <span class="kwrd">value</span>);<br />    <span class="kwrd">public</span> <span class="kwrd">bool</span> IsValidValue(<span class="kwrd">object</span> <span class="kwrd">value</span>);<br />    <span class="kwrd">public</span> <span class="kwrd">void</span> OverrideMetadata(Type forType, PropertyMetadata typeMetadata);<br />    <span class="kwrd">public</span> <span class="kwrd">void</span> OverrideMetadata(Type forType, PropertyMetadata typeMetadata, DependencyPropertyKey key);<br />    <span class="kwrd">public</span> <span class="kwrd">static</span> DependencyProperty Register(<span class="kwrd">string</span> name, Type propertyType, Type ownerType);<br />    <span class="kwrd">public</span> <span class="kwrd">static</span> DependencyProperty Register(<span class="kwrd">string</span> name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata);<br />    <span class="kwrd">public</span> <span class="kwrd">static</span> DependencyProperty Register(<span class="kwrd">string</span> name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback);<br />    <span class="kwrd">public</span> <span class="kwrd">static</span> DependencyProperty RegisterAttached(<span class="kwrd">string</span> name, Type propertyType, Type ownerType);<br />    <span class="kwrd">public</span> <span class="kwrd">static</span> DependencyProperty RegisterAttached(<span class="kwrd">string</span> name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata);<br />    <span class="kwrd">public</span> <span class="kwrd">static</span> DependencyProperty RegisterAttached(<span class="kwrd">string</span> name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback);<br />    <span class="kwrd">public</span> <span class="kwrd">static</span> DependencyPropertyKey RegisterAttachedReadOnly(<span class="kwrd">string</span> name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata);<br />    <span class="kwrd">public</span> <span class="kwrd">static</span> DependencyPropertyKey RegisterAttachedReadOnly(<span class="kwrd">string</span> name, Type propertyType, Type ownerType, PropertyMetadata defaultMetadata, ValidateValueCallback validateValueCallback);<br />    <span class="kwrd">public</span> <span class="kwrd">static</span> DependencyPropertyKey RegisterReadOnly(<span class="kwrd">string</span> name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata);<br />    <span class="kwrd">public</span> <span class="kwrd">static</span> DependencyPropertyKey RegisterReadOnly(<span class="kwrd">string</span> name, Type propertyType, Type ownerType, PropertyMetadata typeMetadata, ValidateValueCallback validateValueCallback);<br />    <span class="kwrd">public</span> <span class="kwrd">override</span> <span class="kwrd">string</span> ToString();<br /><br />    <span class="rem">// Properties</span><br />    <span class="kwrd">public</span> PropertyMetadata DefaultMetadata { get; }<br />    <span class="kwrd">public</span> <span class="kwrd">int</span> GlobalIndex { get; }<br />    <span class="kwrd">public</span> <span class="kwrd">string</span> Name { get; }<br />    <span class="kwrd">public</span> Type OwnerType { get; }<br />    <span class="kwrd">public</span> Type PropertyType { get; }<br />    <span class="kwrd">public</span> <span class="kwrd">bool</span> ReadOnly { get; }<br />    <span class="kwrd">public</span> ValidateValueCallback ValidateValueCallback { get; }<br />}</pre>

      <br /></div>
</li>
<li><strong>DependencyObject</strong>, which provides methods like GetValue, SetValue, ReadLocalValue, CoerceValue, ClearValue to access/modify the value of a dependency property:&#160; 

    <div id="codeSnippetWrapper" class="csharpcode-wrapper">
      <pre id="codeSnippet" class="csharpcode">[TypeDescriptionProvider(<span class="kwrd">typeof</span>(DependencyObjectProvider)), NameScopeProperty(<span class="str">&quot;NameScope&quot;</span>, <span class="kwrd">typeof</span>(NameScope))]<br /><span class="kwrd">public</span> <span class="kwrd">class</span> DependencyObject : DispatcherObject<br />{<br />    <span class="rem">// Methods</span><br />    <span class="kwrd">public</span> DependencyObject();<br />    <span class="kwrd">public</span> <span class="kwrd">void</span> ClearValue(DependencyProperty dp);<br />    <span class="kwrd">public</span> <span class="kwrd">void</span> ClearValue(DependencyPropertyKey key);<br />    <span class="kwrd">public</span> <span class="kwrd">void</span> CoerceValue(DependencyProperty dp);<br />    <span class="kwrd">public</span> <span class="kwrd">sealed</span> <span class="kwrd">override</span> <span class="kwrd">bool</span> Equals(<span class="kwrd">object</span> obj);<br />    <span class="kwrd">public</span> <span class="kwrd">sealed</span> <span class="kwrd">override</span> <span class="kwrd">int</span> GetHashCode();<br />    <span class="kwrd">public</span> LocalValueEnumerator GetLocalValueEnumerator();<br />    <span class="kwrd">public</span> <span class="kwrd">object</span> GetValue(DependencyProperty dp);<br />    <span class="kwrd">public</span> <span class="kwrd">void</span> InvalidateProperty(DependencyProperty dp);<br />    <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> OnPropertyChanged(DependencyPropertyChangedEventArgs e);<br />    <span class="kwrd">public</span> <span class="kwrd">object</span> ReadLocalValue(DependencyProperty dp);<br />    <span class="kwrd">public</span> <span class="kwrd">void</span> SetCurrentValue(DependencyProperty dp, <span class="kwrd">object</span> <span class="kwrd">value</span>);<br />    <span class="kwrd">public</span> <span class="kwrd">void</span> SetValue(DependencyProperty dp, <span class="kwrd">object</span> <span class="kwrd">value</span>);<br />    <span class="kwrd">public</span> <span class="kwrd">void</span> SetValue(DependencyPropertyKey key, <span class="kwrd">object</span> <span class="kwrd">value</span>);<br /><br />    <span class="rem">// Properties</span><br />    <span class="kwrd">public</span> DependencyObjectType DependencyObjectType { get; }<br />    <span class="kwrd">internal</span> <span class="kwrd">uint</span> EffectiveValuesCount { [FriendAccessAllowed] get; <span class="kwrd">private</span> set; }<br />    <span class="kwrd">public</span> <span class="kwrd">bool</span> IsSealed { get; }<br />}</pre>

      <br /></div>
</li>
<li><strong>PropertyMetadata</strong>, which allows the default value, coercion and change handling logic to be specified during dependency property registration:&#160; 

    <div id="codeSnippetWrapper" class="csharpcode-wrapper">
      <pre id="codeSnippet" class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> PropertyMetadata<br />{<br />    <span class="rem">// Methods</span><br />    <span class="kwrd">public</span> PropertyMetadata();<br />    <span class="kwrd">public</span> PropertyMetadata(<span class="kwrd">object</span> defaultValue);<br />    <span class="kwrd">public</span> PropertyMetadata(PropertyChangedCallback propertyChangedCallback);<br />    <span class="kwrd">public</span> PropertyMetadata(<span class="kwrd">object</span> defaultValue, PropertyChangedCallback propertyChangedCallback);<br />    <span class="kwrd">public</span> PropertyMetadata(<span class="kwrd">object</span> defaultValue, PropertyChangedCallback propertyChangedCallback, CoerceValueCallback coerceValueCallback);<br />    <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> Merge(PropertyMetadata baseMetadata, DependencyProperty dp);<br />    <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> OnApply(DependencyProperty dp, Type targetType);<br /><br />    <span class="rem">// Properties</span><br />    <span class="kwrd">public</span> CoerceValueCallback CoerceValueCallback { get; set; }<br />    <span class="kwrd">public</span> <span class="kwrd">object</span> DefaultValue { get; set; }<br />    <span class="kwrd">protected</span> <span class="kwrd">bool</span> IsSealed { get; }<br />    <span class="kwrd">public</span> PropertyChangedCallback PropertyChangedCallback { get; set; }<br />}</pre>

      <br /></div>
</li>
<li>DependencyProperty.Register* methods and their overloads </li>
<li>PropertyMetadata constructors </li>
</ul>
<h3>Example</h3>
<p>The example below has a simple class MyButton, which inherits from Button class and implements a dependency property MyValue. The value of MyValue property must be between 0 to 10, enforced by its validation logic IsValidMyValue(). The effective value of MyValue property depends on its default value(0), user input (set request parameter), and the value of its IsEnabled property inherited from base class. The last dependency is implemented by coercion logic CoerceMyValue and dependency change event handler OnIsEnabledChanged(). Overall the implementation of MyValue demonstrates the common pattern of dependent property on WPF:</p>
<ul>
<li>CLR wrapper: <font face="Fixedsys">public int MyValue { get; set; }</font> </li>
<li>Dependency property identifier: <font face="Fixedsys">public static readonly DependencyProeprty MyValueProperty</font> </li>
<li>Registration with property system: <font face="Fixedsys">DependencyProperty.Register</font>() </li>
<li>Validation logic: <font face="Fixedsys">IsValidMyValue</font> static method </li>
<li>Coercion logic: <font face="Fixedsys">CoerceMyValue</font> static method </li>
</ul>
<p>It is common and advised to also implement changed handling logic via:</p>
<ul>
<li><font face="Fixedsys">PropertyChangedCallback OnMyValueChanged</font> static method </li>
<li><font face="Fixedsys">protected virtual void OnMyValueChanged(oldValue, newValue)</font> to raise the changed event, and for subclass to override </li>
<li><font face="Fixedsys">public static readonly RoutedEvent MyValueChangedEvent</font> routed event identifier and event registration </li>
<li><font face="Fixedsys">public event RoutedPropertyChangedEventHandler&lt;int&gt; MyValueChanged</font> event for client </li>
</ul>
<p>Below is source code of the example:</p>
<ul>
<li>Window1.xaml: 
    <div class="csharpcode-wrapper">
      <pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">Window</span> <span class="attr">x:Class</span><span class="kwrd">=&quot;WpfApp1.Window1&quot;</span>
    <span class="attr">xmlns</span><span class="kwrd">=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;</span>
    <span class="attr">xmlns:x</span><span class="kwrd">=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;</span>
    <span class="attr">xmlns:my</span><span class="kwrd">=&quot;clr-namespace:WpfApp1&quot;</span>
    <span class="attr">Title</span><span class="kwrd">=&quot;Window1&quot;</span> <span class="attr">Height</span><span class="kwrd">=&quot;300&quot;</span> <span class="attr">Width</span><span class="kwrd">=&quot;300&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">StackPanel</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">my:MyButton</span> <span class="attr">x:Name</span><span class="kwrd">=&quot;mybtn&quot;</span> <span class="attr">Content</span><span class="kwrd">=&quot;MyButton&quot;</span> 
                     <span class="attr">MyValueChanged</span><span class="kwrd">=&quot;mybtn_MyValueChanged&quot;</span> <span class="attr">Click</span><span class="kwrd">=&quot;mybtn_Click&quot;</span><span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">StackPanel</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">Window</span><span class="kwrd">&gt;</span></pre>
    </div>
</li>
<li>Window1.xaml.cs: 
    <div class="csharpcode-wrapper">
      <pre class="csharpcode"><span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.Windows;
<span class="kwrd">using</span> System.Windows.Controls;
<span class="kwrd">namespace</span> WpfApp1
{
    <span class="rem">// sample class to demonstrate how to implement a DependencyProperty </span>
    <span class="kwrd">public</span> <span class="kwrd">class</span> MyButton : Button
    {
        <span class="rem">// DP: CLR wrapper</span>
        <span class="kwrd">public</span> <span class="kwrd">int</span> MyValue
        {
            get { <span class="kwrd">return</span> (<span class="kwrd">int</span>)GetValue(MyValueProperty); }
            set { SetValue(MyValueProperty, <span class="kwrd">value</span>); }
        }
        <span class="rem">// DP: dependency property identifier &amp; registration</span>
        <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">readonly</span> DependencyProperty MyValueProperty =
            DependencyProperty.Register(
                <span class="str">&quot;MyValue&quot;</span>, <span class="kwrd">typeof</span>(<span class="kwrd">int</span>), <span class="kwrd">typeof</span>(MyButton),
                <span class="kwrd">new</span> PropertyMetadata(0,
                    <span class="kwrd">new</span> PropertyChangedCallback(OnMyValueChanged),
                    <span class="kwrd">new</span> CoerceValueCallback(CoerceMyValue)),
                <span class="kwrd">new</span> ValidateValueCallback(IsValidMyValue));
        <span class="rem">// DP: validation callback</span>
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> IsValidMyValue(<span class="kwrd">object</span> <span class="kwrd">value</span>)
        {
            <span class="kwrd">int</span> newValue = (<span class="kwrd">int</span>)<span class="kwrd">value</span>;
            <span class="kwrd">return</span> newValue &gt;= 0 &amp;&amp; newValue &lt;= 10;
        }
        <span class="rem">// DP: coercion callback</span>
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">object</span> CoerceMyValue(DependencyObject d, <span class="kwrd">object</span> <span class="kwrd">value</span>)
        {
            MyButton ctrl = (MyButton)d;
            <span class="kwrd">int</span> newValue = (<span class="kwrd">int</span>)<span class="kwrd">value</span>;
            <span class="kwrd">return</span> ctrl.IsEnabled ? Math.Min(5, newValue) : Math.Max(6, newValue);
        }
        <span class="rem">// DP: changed callback</span>
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> OnMyValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MyButton ctrl = (MyButton)d;
            <span class="kwrd">int</span> oldValue = (<span class="kwrd">int</span>)e.OldValue;
            <span class="kwrd">int</span> newValue = (<span class="kwrd">int</span>)e.NewValue;
            ctrl.OnMyValueChanged(oldValue, newValue);
        }
        <span class="rem">// RE: changed event identifier &amp; registration</span>
        <span class="kwrd">public</span> <span class="kwrd">static</span> <span class="kwrd">readonly</span> RoutedEvent MyValueChangedEvent =
            EventManager.RegisterRoutedEvent(<span class="str">&quot;MyValueChanged&quot;</span>, RoutingStrategy.Bubble,
                <span class="kwrd">typeof</span>(RoutedPropertyChangedEventHandler&lt;<span class="kwrd">int</span>&gt;), <span class="kwrd">typeof</span>(MyButton));
        <span class="rem">// RE: changed event</span>
        <span class="kwrd">public</span> <span class="kwrd">event</span> RoutedPropertyChangedEventHandler&lt;<span class="kwrd">int</span>&gt; MyValueChanged;
        <span class="rem">// RE: use a protected virtual to raise event</span>
        <span class="kwrd">protected</span> <span class="kwrd">virtual</span> <span class="kwrd">void</span> OnMyValueChanged(<span class="kwrd">int</span> oldValue, <span class="kwrd">int</span> newValue)
        {
            RoutedPropertyChangedEventArgs&lt;<span class="kwrd">int</span>&gt; e =
                <span class="kwrd">new</span> RoutedPropertyChangedEventArgs&lt;<span class="kwrd">int</span>&gt;(oldValue, newValue);
            e.RoutedEvent = MyValueChangedEvent;
            RaiseEvent(e);
        }
        <span class="rem">// DP: event handler to trigger re-calculation of MyValue because of dependency change</span>
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> OnIsEnabledChanged(<span class="kwrd">object</span> sender, DependencyPropertyChangedEventArgs e)
        {
            MyButton ctrl = (MyButton)sender;
            ctrl.CoerceValue(MyButton.MyValueProperty);
        }
        <span class="kwrd">public</span> MyButton()
        {
            IsEnabledChanged += OnIsEnabledChanged;
        }
    }
    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// Interaction logic for Window1.xaml</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> Window1 : Window
    {
        <span class="kwrd">public</span> Window1()
        {
            InitializeComponent();
        }
        <span class="kwrd">private</span> <span class="kwrd">void</span> mybtn_Click(<span class="kwrd">object</span> sender, RoutedEventArgs e)
        {
        }
        <span class="kwrd">private</span> <span class="kwrd">void</span> mybtn_MyValueChanged(<span class="kwrd">object</span> sender, RoutedPropertyChangedEventArgs&lt;<span class="kwrd">int</span>&gt; e)
        {
            <span class="kwrd">int</span> oldValue = e.OldValue;
            <span class="kwrd">int</span> newValue = e.NewValue;
        }
    }
}</pre>
    </div>
</li>
</ul>
<h3>How Dependency Property Work on WPF</h3>
<p>To demonstrate how dependency property works on WPF, I set a break point on most functions, and used the Immediate debug window to check values and change states.</p>
<h4>Registration</h4>
<ul>
<li>When the program starts, DependencyProperty.Register is executed, which in turn calls IsValidMyValue to validate the default value 0:<br />
    <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp1.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="validation called for default value" border="0" alt="validation called for default value" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp1_thumb.png" width="584" height="435" /></a> </li>
</ul>
<h4>Effective Value</h4>
<p>Click on the MyButton instance to trigger the break point on mybtn_Click event handler, then use the Immediate window to check on MyValue property. As shown below:</p>
<ul>
<li>Even though mybtn.MyValue isn&#8217;t assigned any value, it has an effective value of 0, the default value of this dependency property, as shown by results of mybtn.MyValue and mybtn.GetValue. </li>
<li>It is important that the CLR wrapper and GetValue/SetValue calls should always have the same effect. This is done by the CLR wrappers being just a wrapper for GetValue/SetValue and nothing more. </li>
<li>mybtn.ReadLocalValue(MyButton.MyValueProperty) results shows that there is no local storage for MyValue property on mybtn instance. </li>
<li>When mybtn.MyValue takes initial value, there is no change notification, as OnMyValueChanged isn&#8217;t called at program start.
<p><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp2.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="DP has default value, no local storage" border="0" alt="DP has default value, no local storage" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp2_thumb.png" width="584" height="435" /></a> </li>
</ul>
<h4>Validation</h4>
<p>In Immediate window, set mybtn.MyValue to an invalid value -1 by typing in command &quot;mybtn.MyValue = -1&quot;:</p>
<ul>
<li>The CLR wrapper is called, which in turn calls SetValue, which triggers validation on the new value -1.<br />
    <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp3.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="validation called for setting value" border="0" alt="validation called for setting value" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp3_thumb.png" width="584" height="435" /></a> </li>
<li>IsValidMyValue returns false on the new value -1, WPF property system then throws ArgumentException:<br />
    <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp4.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="validation failure triggers argument exception in setting" border="0" alt="validation failure triggers argument exception in setting" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp4_thumb.png" width="584" height="435" /></a> </li>
<li>Check the value of MyValue via three ways: CLR wrapper, GetValue, ReadLocalValue: nothing changed. This is important, since on Silverlight state does change, even for invalid set operation, so we have to write code to restore the state, as I will show in part two of the series.<br />
    <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp5.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="No state change after invalid set operation" border="0" alt="No state change after invalid set operation" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp5_thumb.png" width="584" height="435" /></a> </li>
</ul>
<h4>Coercion</h4>
<p>Again in Immediate window, try set mybtn.MyValue to 8, which is valid, but because mybtn.IsEnabled is true, the effective value must be less than or equal to 5:</p>
<ul>
<li>First, validation is called on the new value 8, via CLR wrapper and SetValue:<br />
    <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp6.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="validation called during setting" border="0" alt="validation called during setting" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp6_thumb.png" width="584" height="435" /></a> </li>
<li>IsValidMyValue(8) returns true, so coercion logic CoerceMyValue is called, via CLR wrapper, SetValue, UpdateEffectiveValue, and ProcessCoerceValue:<br />
    <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp7.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Coercion called during setting" border="0" alt="Coercion called during setting" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp7_thumb.png" width="584" height="435" /></a>&#160; </li>
<li>CoerceMyValue(8) returns a different value 5, so WPF property system calls IsValidMyvalue on the coerced effective value 5:<br />
    <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp8.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Coerced value goes through validation as well" border="0" alt="Coerced value goes through validation as well" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp8_thumb.png" width="584" height="435" /></a> </li>
<li>IsValidMyValue(5) returns true, so WPF property system calls changed logic OnMyValueChanged, with oldValue as 0 and newValue as 5. Both values are effective values, since there was no old value in mybtn instance, and the new value is actually 8. OnMyValueChanged in turns call its proctected virtual version, which raises MyValueChanged routed event, and executes MyValueChanged event handlers, if there is any.&#160; <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp9.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Changed callback to raise changed event" border="0" alt="Changed callback to raise changed event" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp9_thumb.png" width="584" height="435" /></a> </li>
<li>Check the value of MyValue property: both CLR wrapper and GetValue return the new effective value 5, but GetLocalValue returns 8, remembering the original user request. This is very important, as we will see next.<br />
    <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp10.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Coercion causes local value and effective value difference" border="0" alt="Coercion causes local value and effective value difference" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp10_thumb.png" width="584" height="435" /></a> </li>
</ul>
<h4>Dynamic Re-calculation as Dependency Changes</h4>
<p>Now let&#8217;s set mybtn.IsEnabled to false in Immediate window. This changes one of the dependencies for MyValue, which should trigger re-calculation of the effective value of MyValue property, if I have coded it right (and I did, of course <img src='http://www.ningzhang.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> :</p>
<ul>
<li>First, please note that IsEnabled change processing is synchronous, i.e., OnIsEnabledChanged is called before &quot;mybtn.IsEnabled = false&quot; returns. This is important since IsEnabled change handling is asynchronous on Silverlight. </li>
<li>We have to trigger the recalculation since the property system doesn&#8217;t know MyValue depends on IsEnabled. This is done by handling IsEnabledChanged event (IsEnabledChanged += OnIsEnabledChanged in MyButton()) and call CoerceValue from inside OnIsEnabledChanged event handler. </li>
<li>CoerceValue in trun calls UpdateEffectiveValue, ProcessCoerceValue, and then our coercion logic CoerceMyValue. Please note that CoerceMyValue is called with newValue of 8, not the current effective value 5. The original set request parameter 8 is remembered by mybtn instance locally, as shown by ReadLocalValue result before. This is important, since Silverlight doesn&#8217;t do this, which makes implementing coercion very tricky, as will be shown in part 3 of the blog series with bugs in Silverlight RangeBase and its subclasses like Slider and ScrollBar.<br />
    <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp11.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Dependency change triggers coercion" border="0" alt="Dependency change triggers coercion" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp11_thumb.png" width="584" height="435" /></a> </li>
<li>Since mybtn.IsEnabled is now false, the originally requested value 8 becomes valid, so CoerceMyValue returns 8. </li>
<li>8 is different from previous effective value of 5, so UpdateEffectieValue calls NotifyPropertyChange, which ultimately calls our changed logic OnMyValueChanged with oldValue of 5 and newValue of 8. This happens even though there is no new set operation for MyValue property. It is the IsEnabled dependency change that caused MyValue effective value change, which in turns triggers change notification and event handling for MyValue property, and this is all happening synchronously.<br />
    <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp12.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Coercion triggers change notification" border="0" alt="Coercion triggers change notification" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp12_thumb.png" width="584" height="435" /></a> </li>
<li>After the coercion, change notification, and event handling finishes, check the value of MyValue property: now all three methods (mybtn.MyValue, mybtn.GetValue, mybtn.ReadLocalValue) return the same result.<br />
    <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp13.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Effective value and local value the same" border="0" alt="Effective value and local value the same" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp13_thumb.png" width="584" height="435" /></a> </li>
<li>one last experiment: type mybtn.ClearValue(MyButton.MyValueProperty) in Immediate window to clear the local value (8) of the dependency property, which in turn triggers change handling logic OnMyValueChanged, with newValue of 0, the new effective value derived from MyValue&#8217;s default property.<br />
    <br /><a href="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp14.png" target="_blank"><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ClearValue triggers change handling" border="0" alt="ClearValue triggers change handling" src="http://www.ningzhang.org/wp-content/uploads/2009/12/wpfdp14_thumb.png" width="584" height="435" /></a> </li>
</ul>
<h3>Conclusion</h3>
<p>As we can see from above example and experiment, WPF has a powerful property system, which makes both implementing and using dependency properties very easy. It is a lot trickier on Silverlight though, because Silverlight only implements a subset of WPF functionality. In part two of the post series, I will re-implement above example on Silverlight, and demonstrate the difference between WPF and Silverlight. In part three, I will use RangeBase and NumericUpDown to demonstrate the gotcha on Silverlight, which is the original motivation for this post series. Stay tuned!</p>
<p>PS: the first post of the series ended up a lot longer and more time consuming than I expected, so I will stop here. If there is enough interest, I can upload the project for you to experiment, and a code snippet that provides most of the plumbing for implementing dependency property on WPF. Thanks!</p>
<p>&#160;</p>
<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e0db3315-cec8-444e-a584-488a7464d975" class="wlWriterSmartContent">Technorati Tags: <a href="http://technorati.com/tags/Dependency%20Property" rel="tag">Dependency Property</a>,<a href="http://technorati.com/tags/WPF" rel="tag">WPF</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.ningzhang.org/2008/11/07/dependencyproperty-validation-coercion-change-handling-part-i-wpf/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

