<?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/"
	>

<channel>
	<title>Ioan Lazarciuc's Weblog</title>
	<atom:link href="http://www.lazarciuc.ro/ioan/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lazarciuc.ro/ioan</link>
	<description>I program, therefore I exist.</description>
	<pubDate>Mon, 09 Nov 2009 18:07:26 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>WCF Contract Limits?</title>
		<link>http://www.lazarciuc.ro/ioan/2009/05/28/wcf-contract-limits/</link>
		<comments>http://www.lazarciuc.ro/ioan/2009/05/28/wcf-contract-limits/#comments</comments>
		<pubDate>Wed, 27 May 2009 21:42:06 +0000</pubDate>
		<dc:creator>cretz</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[metadata exchange]]></category>

		<category><![CDATA[readerQuotas]]></category>

		<category><![CDATA[wcf]]></category>

		<guid isPermaLink="false">http://www.lazarciuc.ro/ioan/2009/05/28/wcf-contract-limits/</guid>
		<description><![CDATA[Today I’ve hit the size limit for a WCF service contract. It might seem unbelievable, but it’s almost true.
 
I have a service contract with about 40 operations. After adding a new method to the contract, I get an error from the WCF Test Client:
Error: Cannot obtain Metadata from http://localhost:8731/Design_Time_Addresses/CDA.Services/ApplicationService/mex If this is a Windows [...]]]></description>
			<content:encoded><![CDATA[<p>Today I’ve hit the size limit for a WCF service contract. It might seem unbelievable, but it’s almost true.</p>
<p> <span id="more-28"></span>
<p>I have a service contract with about 40 operations. After adding a new method to the contract, I get an error from the WCF Test Client:</p>
<blockquote><p><em>Error: Cannot obtain Metadata from </em><a href="http://localhost:8731/Design_Time_Addresses/CDA.Services/ApplicationService/mex"><em>http://localhost:8731/Design_Time_Addresses/CDA.Services/ApplicationService/mex</em></a><em> If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address.&#160; For help enabling metadata publishing, please refer to the MSDN documentation at </em><a href="http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata"><em>http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata</em></a><em> Exchange Error&#160;&#160;&#160; URI: </em><a href="http://localhost:8731/Design_Time_Addresses/CDA.Services/ApplicationService/mex"><em>http://localhost:8731/Design_Time_Addresses/CDA.Services/ApplicationService/mex</em></a><em>&#160;&#160;&#160; Metadata contains a reference that cannot be resolved: &#8216;</em><a href="http://localhost:8731/Design_Time_Addresses/CDA.Services/ApplicationService/mex'"><em>http://localhost:8731/Design_Time_Addresses/CDA.Services/ApplicationService/mex&#8217;</em></a><em>.&#160;&#160;&#160; There is an error in XML document (1, 110009).&#160;&#160;&#160; The value for the &#8216;base&#8217; attribute is invalid - &#8216;q1:EntityObject&#8217; is an invalid value for the &#8216;base&#8217; attribute..HTTP GET Error&#160;&#160;&#160; URI: </em><a href="http://localhost:8731/Design_Time_Addresses/CDA.Services/ApplicationService/mex"><em>http://localhost:8731/Design_Time_Addresses/CDA.Services/ApplicationService/mex</em></a><em>&#160;&#160;&#160; There was an error downloading &#8216;</em><a href="http://localhost:8731/Design_Time_Addresses/CDA.Services/ApplicationService/mex'"><em>http://localhost:8731/Design_Time_Addresses/CDA.Services/ApplicationService/mex&#8217;</em></a><em>.&#160;&#160;&#160; The request failed with HTTP status 400: Bad Request.</em></p>
</blockquote>
<p>Same error if i attempt to add this service to a project. The message seems to change depending on which method I leave out, or put in. It seems to be getting hilarious, but it’s not. Accidentally, i got this error(truncated):</p>
<blockquote><p><em>There is an error in XML document The maximum nametable character count quota (16384) has been exceeded while reading XML data.</em></p>
</blockquote>
<p>After a bit of searching online, I found out that this is a recognized issue with the default metadata exchange binding, <a href="http://social.msdn.microsoft.com/forums/en-US/wcf/thread/17592561-c470-452a-a52c-2a5a2839582c/" target="_blank">here</a>. The workarounds didn’t look good at all to me, so I continued searching. Then, I came across <a href="http://msdn.microsoft.com/en-us/library/aa395212.aspx" target="_blank">this</a>, which looks a lot more promising.</p>
<p>I created a custom wsHttpBinding that I used for the meta data contract. Now the task was to get the Visual Studio IDE and the WCF Test Client to use this binding when adding or updating a service reference. In order for this, corresponding bindings must be configured for each tool, in its .exe.config file. The binding must be identical with the one on the service side, and it must have a name that corresponds to the protocol used by it (http, https, net.tcp).</p>
<p>There are 3 places(files) that need to be updated: devenv.exe.config, WcfTestClient.exe.config and SvcUtil.exe.config. Actually, if you have several versions of the Windows SDK installed, you might have more than 3 places to modify. My advice is to do a search for each of the config file names and change as many of them as required in order to get your work back on track.</p>
<p>I would have thought that the mexHttp(s)Binding would allow for custom quotas for the reader. Perhaps in .NET 4.0? (vote <a href="https://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=459384" target="_blank">here</a> if it hurts)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lazarciuc.ro/ioan/2009/05/28/wcf-contract-limits/feed/</wfw:commentRss>
		</item>
		<item>
		<title>XNA Streaming - Part4</title>
		<link>http://www.lazarciuc.ro/ioan/2009/03/23/xna-streaming-part4/</link>
		<comments>http://www.lazarciuc.ro/ioan/2009/03/23/xna-streaming-part4/#comments</comments>
		<pubDate>Mon, 23 Mar 2009 15:16:15 +0000</pubDate>
		<dc:creator>cretz</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[xna streaming]]></category>

		<guid isPermaLink="false">http://www.lazarciuc.ro/ioan/2009/03/23/xna-streaming-part4/</guid>
		<description><![CDATA[In the previous parts of this articles I’ve talked about the service components of the XNA Streaming system. In this part, I’m going to talk about the Communication Broker.
The role of the Communication Broker is to cover the communication with the Streaming Service. By doing so, the code required of client applications is simplified, and [...]]]></description>
			<content:encoded><![CDATA[<p>In the previous parts of this articles I’ve talked about the service components of the XNA Streaming system. In this part, I’m going to talk about the Communication Broker.</p>
<p>The role of the Communication Broker is to cover the communication with the Streaming Service. By doing so, the code required of client applications is simplified, and less duplicate code will be generated for each application using the system. the broker also caches all variable changes and periodically sends all changes accumulated to the service, thus reducing the number of calls per second required by a single client to a predictable amount.</p>
<p> <span id="more-27"></span>
<p>The broker uses a synchronized queue to accumulate changes and a timer to periodically clear the queue and send the resulting TimeSlice to the Streaming service. A receive background worker is used to reconstruct changes received from the Streaming service and raise appropriate UpdateProperty events.</p>
<p>The main operations provided by the broker are:</p>
<p><strong>Start:</strong> used to start the processing of the broker by registering with the Streaming service. If the game is run in broadcast mode, this method starts the timer for the periodical TimeSlice send. If in observer mode, the broker requests the whole state from the Streaming service and raises the UpdateGameState event, to allow the application to initialize its state.</p>
<p><strong>Stop:</strong> used to stop broker processing and to unregister from the Streaming service.</p>
<p>The events exposed by the broker are UpdateProperty, UpdateGameState and OutOfSynch. The first two events are to be sued by the application to change the value of a single property, or of all properties controlled by the XNA Streaming system. The OutOfSynch event is raised whenever the intervals between two consecutive slices do not match. The application can decide what to do at this point; for example, it could ask for the whole state of the game from the broker, which in turn would make the request to the Streaming service.</p>
<p>The application has to implement the GetCurrentState method of the IObservableGame interface in order to provide the broker with the current state of the application when needed.</p>
<h3>Considerations for Writing Applications</h3>
<p>There are some aspects that have to be taken into account when writing or adapting applications that use the XNA Streaming system.</p>
<p>User input has to be converted to changes of values. For example, mouse movement in a 3D environment can be translated into a set of 3 camera angles that completely define the way the camera is pointing. Pressing a button can be translated into a boolean flag set to true.</p>
<p>For simplicity, (most) user input should be ignored when in observe mode in order to avoid conflicts in UI commands that could have unpredictable effects.</p>
<p>One should take into careful consideration whether a piece of information is a “user input” variable, or a result of a law being applied to an initial value. Variables that are not broadcast have a high chance of being out of synch between the broadcaster and the observers. If the effect of such a variable is not critical (e.g. hit/miss decision) then it can be left out of the TimeSlice. Otherwise, one might discover that it is possible to miss a target, but hit it at the replay.</p>
<h3>Results</h3>
<p>The resulting prototype of the XNA Streaming system was presented at the 2008 edition of the Romanian Microsoft Community Bootcamp.</p>
<p><a href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2009/03/img-3595.jpg"><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="IMG_3595" border="0" alt="IMG_3595" src="http://www.lazarciuc.ro/ioan/wp-content/uploads/2009/03/img-3595-thumb.jpg" width="452" height="303" /></a> </p>
<h3>Conclusion</h3>
<p>The XNA Streaming system is a good first prototype or toy, but it is by no means a decent communication framework. Aspects such as security, collaboration, dynamic send permissions, multicast, unicast and data conflict resolution have to be solved in order to obtain a communication framework.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lazarciuc.ro/ioan/2009/03/23/xna-streaming-part4/feed/</wfw:commentRss>
		</item>
		<item>
		<title>XNA Streaming &#8211; Part 3</title>
		<link>http://www.lazarciuc.ro/ioan/2009/02/27/xna-streaming-part-3/</link>
		<comments>http://www.lazarciuc.ro/ioan/2009/02/27/xna-streaming-part-3/#comments</comments>
		<pubDate>Fri, 27 Feb 2009 18:43:15 +0000</pubDate>
		<dc:creator>cretz</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[streaming]]></category>

		<category><![CDATA[xna]]></category>

		<guid isPermaLink="false">http://www.lazarciuc.ro/ioan/2009/02/27/xna-streaming-part-3/</guid>
		<description><![CDATA[After quite a long break, I resume the series of articles on my XNA Streaming project by describing the actual Stream Service component. This component is responsible for transmitting the broadcast information to all connected users.
The information is encoded in (&#60;property name&#62;, &#60;value&#62;) pairs. All serializable data types are supported for values. Users register with [...]]]></description>
			<content:encoded><![CDATA[<p>After quite a long break, I resume the series of articles on my XNA Streaming project by describing the actual Stream Service component. This component is responsible for transmitting the broadcast information to all connected users.</p>
<p>The information is encoded in (&lt;property name&gt;, &lt;value&gt;) pairs. All serializable data types are supported for values. Users register with the Stream Service either as Broadcaster or as Observer. After this step, the Broadcaster uses the service to send updates for information (property-value pairs). Observers get notified by the service of the updated information via a IXNAStreamCallback callback contract, a feature of WCF services.</p>
<p><span id="more-22"></span></p>
<p>Updates for a certain variable can occur at a very high frequency (camera angle in a 3D application). If a separate call to the service would be generated every few milliseconds, then the service would easily become overwhelmed by the calls. The solution chosen is to “buffer” several information changes and send them all at time, at set time intervals. We name this “buffer” a TimeSlice. A time slice has a Duration and several time slice entries. A TimeSliceEntry has a PropertyName, a Value and a SliceOffset, used to express the time since the beginning of the TimeSlice when the value change has occurred. This way we gain control over the number of calls made to the service.</p>
<p>The Stream Service provides the following operations:</p>
<p><strong>RegisterCallback:</strong> used to register with an application (given by name) for a role (given as a member of a GameMode enumeration). Only one Broadcaster can exist. This operation involves storing a user’s callback interface instance in a dictionary that has the application’s name as key and a list of callback interfaces (IXNAStreamCallback) instances.</p>
<p><strong>UnregisterCallback:</strong> used to safely end a registration with an application (if a client does not unregister, sending updates or requesting the overall state would fail).</p>
<p><strong>UpdateStateVariables:</strong> used to send a TimeSlice to all subscribers of an application. This is the actual method that performs the broadcast. It uses a method defined in the callback contract to broadcast the TimeSlice to all registered clients except the broadcaster.</p>
<p><strong>GetCurrentState:</strong> to be used by an Observer in order to resynchronize with the broadcaster. This method should be called right after registering with an application. The GameState returned is a collection of game state entries. Each GameStateEntry contains a Key (the name of the variable) and a Value. The Stream Service request the current GameState from the Broadcaster via the callback contract.</p>
<p>The IXNAStreamCallback contract contains the following operations:</p>
<p><strong>StateVariablesChanged:</strong> service calls this method for Observers whenever it receives a TimeSlice from the Broadcaster. It is up to the client to reconstruct the information changes in the TimeSlice with proper timing.</p>
<p><strong>GetCurrentState:</strong> service calls this method for the Broadcaster whenever it receives a corresponding request from an Observer. The method returns the current GameState.</p>
<p>The Stream Service does not provide complex functionality, in order to make the actual information broadcast as fast as possible. The more complex functionality is implemented in the Communication Broker, that will be described in the next part of the series.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lazarciuc.ro/ioan/2009/02/27/xna-streaming-part-3/feed/</wfw:commentRss>
		</item>
		<item>
		<title>XNA Streaming - Part 2</title>
		<link>http://www.lazarciuc.ro/ioan/2008/10/26/xna-streaming-part-2/</link>
		<comments>http://www.lazarciuc.ro/ioan/2008/10/26/xna-streaming-part-2/#comments</comments>
		<pubDate>Sat, 25 Oct 2008 23:31:03 +0000</pubDate>
		<dc:creator>cretz</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[streaming]]></category>

		<category><![CDATA[xna]]></category>

		<guid isPermaLink="false">http://www.lazarciuc.ro/ioan/2008/10/26/xna-streaming-part-2/</guid>
		<description><![CDATA[In part one of this article, I did an overview of the XNA Streaming project. In this part I’m going to describe the File Transfer Service.
The main responsibility of the File Transfer Service is to provide access to streamable games. The service stores the game files in a database table, together with their relative file [...]]]></description>
			<content:encoded><![CDATA[<p>In <a target="_blank" href="http://www.lazarciuc.ro/ioan/2008/09/21/xna-streaming-part-1/" title="XNA Stremaing - Part 1">part one</a> of this article, I did an overview of the XNA Streaming project. In this part I’m going to describe the File Transfer Service.</p>
<p>The main responsibility of the File Transfer Service is to provide access to streamable games. The service stores the game files in a database table, together with their relative file paths. This way the file system structure can be recreated when downloading the game. The game’s name, author and a short description are also stored in another table.</p>
<p><span id="more-21"></span></p>
<p>The operations that the File Transfer Service supports are:</p>
<ul>
<li>Create a game with no files: This operation simply creates a game entity with the game’s name, author and description with no files.</li>
<li>Upload a file for an already created game: This operation stores a file together with it’s relative path to the game’s folder for a previously created game. This operation gets invoked for each file in a game’s folder.</li>
<li>Delete a game: Removes a game from the database together with its files.</li>
<li>Get all uploaded games: This operation returns a collection of general information about uploaded games (game name, uploader and description).</li>
<li>Get all relative file paths for a game: This operation returns a collection containing the relative paths for all the files of a game. This list can be used to download each file and save locally.</li>
<li>Download a file from a game: This operation downloads a file specified by the game to which it belongs and its relative path to the game folder.</li>
<li>Get start up information for a game: This operation returns the game’s name, which is used to identify the streamed game at runtime, the address and endpoint name for the Streaming service. This information is used to start a game, both in observe or in broadcast mode.</li>
</ul>
<p>The download/upload of each file takes place through streaming. This limits the in memory portion of a potentially large file at any moment to the size of the buffer of the stream. Stream parameters and return values are a feature of WCF services.</p>
<p>The File Streaming Service has as UI an <a target="_blank" href="http://msdn.microsoft.com/en-us/library/aa970060.aspx">XBAP</a> that helps in uploading, downloading and starting a game.</p>
<p><a href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/XNAStreamingPart2_99B5/image.png"><img border="0" width="426" src="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/XNAStreamingPart2_99B5/image_thumb.png" alt="image" height="261" style="display: inline; border-width: 0px" title="image" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lazarciuc.ro/ioan/2008/10/26/xna-streaming-part-2/feed/</wfw:commentRss>
		</item>
		<item>
		<title>XNA Streaming - Part 1</title>
		<link>http://www.lazarciuc.ro/ioan/2008/09/21/xna-streaming-part-1/</link>
		<comments>http://www.lazarciuc.ro/ioan/2008/09/21/xna-streaming-part-1/#comments</comments>
		<pubDate>Sat, 20 Sep 2008 21:38:53 +0000</pubDate>
		<dc:creator>cretz</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[streaming]]></category>

		<category><![CDATA[xna]]></category>

		<guid isPermaLink="false">http://www.lazarciuc.ro/ioan/2008/09/21/xna-streaming-part-1/</guid>
		<description><![CDATA[Introduction
As I mentioned in my previous post, at this year&#8217;s Microsoft Community Bootcamp I entered in the demo competition together with Adi. We&#8217;ve had some issues in the past with (cheap) broadcasting of presentations. There are plenty of professional tools out there that accomplish this goal, but that&#8217;s not my point. My point is that [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>As I mentioned in my previous <a href="http://www.lazarciuc.ro/ioan/2008/09/18/microsoft-community-bootcamp-v5/" target="_blank">post</a>, at this year&#8217;s Microsoft Community Bootcamp I entered in the demo competition together with <a href="http://adimuresan.wordpress.com/" target="_blank">Adi</a>. We&#8217;ve had some issues in the past with (cheap) broadcasting of presentations. There are plenty of professional tools out there that accomplish this goal, but that&#8217;s not my point. My point is that I have not yet found a cheap (free) utility that will allow me to give a presentation to several viewers that may not be in the same room (or the screen isn&#8217;t big enough for the whole audience).</p>
<p>Given this background, Adi proposed we create a way in which several people can see the same thing that a broadcaster transmits. Further, the &#8220;thing&#8221; that everyone sees is actually an XNA game, that could might as well be an interactive presentation in 3D.</p>
<p><span id="more-20"></span></p>
<h3>Description</h3>
<p>The main idea is that, given an XNA game (possibly a game that did not take into consideration broadcasting though our &#8220;system&#8221;), produce a mechanism such that a <em>broadcaster</em> can transmit the content on the screen to any number of <em>observers</em>. As infrastructure for communication a WCF service was chosen. The reason for this is because it is relatively quick to implement and set up, it supports binary protocols and also bidirectional, asynchronous communication via service callbacks.</p>
<p>The first idea that comes to mind when deciding what to broadcast is whole images, pixel by pixel. The trouble with this is that if we have an application with resolution of 800&#215;600 pixels, 32 bit color depth, at 60 frames/second, then we would require at least 109 MBytes/second/observer. This is totally unacceptable. Even with video compression, it would still require substantial bandwidth.</p>
<p>Instead, we decided that we could reduce the whole state of a game to a few state variables and a few &#8220;laws&#8221; that govern how these state variables evolve in time. Transmitting only some state variables proves to require much less bandwidth than transmitting the whole image. To further reduce the size of the messages transmitted, we identified 2 categories of state variables: the ones that are directly influenced by a user (through keyboard input for example), and the ones that have an initial value, and a law that dictates it&#8217;s evolution in time. The state variables that evolve independent of user input can be left out of the &#8220;frame-by-frame&#8221; transmissions, and just the initial value has to be transmitted.</p>
<h3>XNA Streaming Components</h3>
<p>Given the initial description of the system proposed, we decided initially on three components:</p>
<p>The Streaming Service, that would receive calls from the broadcaster when state variables change and then transmit those changes through callbacks to all the subscribed observers. Aside from this main communication channel, the Streaming Service also provides initial synchronization for observers, meaning the service prompts the broadcaster (through a callback) to send the whole game state each time a new observer connects.</p>
<p>The File Transfer Service is responsible for storing all &#8220;broadcastable&#8221; game binaries,  delivering them to clients and providing startup information for each game (Streaming Service address).</p>
<p>The actual game, which has to be able to run in two modes: broadcast and observer. The game makes service calls to transmit/request state variables and responds to the callbacks of the Streaming Service.</p>
<p>At this point we analysed the communication between the game and the Streaming Service. Everything seemed fine, except for one detail: if we have a camera component that provides tens if not hundreds of new values every second, and we take into consideration that we have more than just the camera in a game, we can see that the number of service method calls performed by the broadcaster to transmit state variable changes is in the order of hundreds (at least) per second. This will cripple the service, regardless of the hardware it runs on (provided we stick to the &#8220;cheap&#8221; area&#8230;). A way to seriously cut down the number of service method calls was needed.</p>
<p>One way to reduce the service calls is to buffer the state variable changes, i.e. store each value together with the time at which the change occurred, and after a specific amount of time, send all buffered variable changes to the service, which in turn redistributes them to the observers, which reconstruct the sequence of state variable changes using the information received and timers. We call each such buffer a TimeSlice, and a touple of the form &lt;VarName, VarValue, TimeSpan&gt; a SliceEntry, where the TimeSpan is the time interval passed since the beginning of the current TimeSlice.</p>
<p>At this point we decided to call the new component a CommunicationBroker. It became clear that all code that would involve the Streaming Service would now be placed in the CommunicationBroker, and that sending calls/responding to the Streaming Service can be abstracted through this broker. In fact we now obtained an XNA Streaming Framework. This significantly reduces the complexity of the code that is necessary in the streamed game. Further more, now we had an actual streaming part, we stream the variable changes.</p>
<p>This is the end of part one of the article. In subsequent parts, I will describe each component in more detail and present some preliminary test results.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lazarciuc.ro/ioan/2008/09/21/xna-streaming-part-1/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Microsoft Community Bootcamp v5</title>
		<link>http://www.lazarciuc.ro/ioan/2008/09/18/microsoft-community-bootcamp-v5/</link>
		<comments>http://www.lazarciuc.ro/ioan/2008/09/18/microsoft-community-bootcamp-v5/#comments</comments>
		<pubDate>Wed, 17 Sep 2008 21:53:55 +0000</pubDate>
		<dc:creator>cretz</dc:creator>
		
		<category><![CDATA[Community]]></category>

		<guid isPermaLink="false">http://www.lazarciuc.ro/ioan/2008/09/18/microsoft-community-bootcamp-v5/</guid>
		<description><![CDATA[During 11.09.2008 and 14.09.2008 I attended the fifth annual event dedicated to Microsoft professionals from the industry and academic environment. I also attended last year and wrote a bit about the experience here. A change from last year&#8217;s event was the fact that this year, the professionals invited were almost as many as MSPs (until [...]]]></description>
			<content:encoded><![CDATA[<p><a title="IMG_0047" href="http://www.flickr.com/photos/12744616@N08/2860921788/"><img alt="IMG_0047" src="http://static.flickr.com/3051/2860921788_9f9b1e8819_m.jpg" align="left" border="0" /></a>During 11.09.2008 and 14.09.2008 I attended the fifth annual event dedicated to Microsoft professionals from the industry and academic environment. I also attended last year and wrote a bit about the experience <a href="http://www.lazarciuc.ro/ioan/2007/09/06/microsoft-community-bootcamp/" target="_blank">here</a>. A change from last year&#8217;s event was the fact that this year, the professionals invited were almost as many as MSPs (until now,&#160; only a handful of MVPs had been invited). The location was Vatra Dornei. Possibly due to the fact that the bootcamp was held later than last year, it was much colder (and so we were &quot;encouraged&quot; to stay indoors or dress &quot;heavily&quot;).</p>
<p><span id="more-19"></span></p>
<p>We all received a book on blogging and one on how to overcome disadvantages that prevent you from continuing your path on the road to (more) success (yes, it sounds a bit cheesy, but the book might be insightful). Keeping the inspirational note, the event&#8217;s T-shirt featured Microsoft&#8217;s <a href="http://www.microsoft-watch.com/content/corporate/microsofts_blue_monster.html" target="_blank">Blue Monster</a>, and the attached slogan: &quot;Change the world or go home&quot;.</p>
<p>The first day was dedicated to MSP presentations. We started with some laughs as each university team lead stepped up and presented last year&#8217;s achievements in a rather &quot;fashionable&quot; way&#8230;</p>
<table cellspacing="0" cellpadding="2" width="404" border="0">
<tbody>
<tr>
<td valign="top" width="103"><a title="Step up!" href="http://www.flickr.com/photos/12744616@N08/2857033894/"><img alt="Step up!" src="http://static.flickr.com/3071/2857033894_052b41c93a_t.jpg" border="0" /></a></td>
<td valign="top" width="106"><a title="IMG_0011" href="http://www.flickr.com/photos/12744616@N08/2860054185/"><img alt="IMG_0011" src="http://static.flickr.com/2018/2860054185_0377a9513e_t.jpg" border="0" /></a></td>
<td valign="top" width="108"><a title="IMG_0038" href="http://www.flickr.com/photos/12744616@N08/2860905560/"><img alt="IMG_0038" src="http://static.flickr.com/3064/2860905560_a53aa1f617_t.jpg" border="0" /></a></td>
<td valign="top" width="85"><a title="IMG_0023" href="http://www.flickr.com/photos/12744616@N08/2860066179/"><img alt="IMG_0023" src="http://static.flickr.com/3199/2860066179_cc0a34421c_t.jpg" border="0" /></a></td>
</tr>
</tbody>
</table>
<p>An interesting point was the demo competition. Myself and <a href="http://adimuresan.wordpress.com/" target="_blank">Adi</a> participated with a project named XNA Streaming (<a href="http://www.catalinzima.com/" target="_blank">Cata</a> will, again, correct me into saying it&#8217;s XNA Framework Content Streaming) that uses WCF to transmit a set of data from one XNA Framework application to another one, the aim being to obtain the same &quot;content&quot; on each machine. I&#8217;ll get back with a post on how we did it (for real this time <img src='http://www.lazarciuc.ro/ioan/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> ). The only competition was <a href="http://blog.nadas.ro/" target="_blank">Mihai Nadas</a>, with Acoustic Fingerprints. The two ideas were really nice (as nice as the one that won last year&#8217;s competition), but I was a bit disappointed by the lack of competition. The outcome? Both projects were declared winners, and each won an XBOX 360 for their MSP team.</p>
<table cellspacing="0" cellpadding="2" width="461" border="0">
<tbody>
<tr>
<td valign="top" width="229"><a href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/MicrosoftCommunityBootcampv5_14D47/IMG_3596.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="151" alt="IMG_3596" src="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/MicrosoftCommunityBootcampv5_14D47/IMG_3596_thumb.jpg" width="224" border="0" /></a></td>
<td valign="top" width="230"><a href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/MicrosoftCommunityBootcampv5_14D47/IMG_3600.jpg"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="151" alt="IMG_3600" src="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/MicrosoftCommunityBootcampv5_14D47/IMG_3600_thumb.jpg" width="224" border="0" /></a></td>
</tr>
</tbody>
</table>
<p>The rest of the day was filled with more presentations on being a good technology evangelist. No fun in the first day&#8230; well, at least not &quot;organized&quot; fun. We managed to spread across the hotel&#8217;s lobby and use it&#8217;s wireless network to play some LAN games in the evening.</p>
<table cellspacing="0" cellpadding="2" width="401" border="0">
<tbody>
<tr>
<td valign="top" width="199"><a title="Boss man" href="http://www.flickr.com/photos/12744616@N08/2856227087/"><img height="100" alt="Boss man" src="http://static.flickr.com/3276/2856227087_94b816a72d_t.jpg" width="133" border="0" /></a></td>
<td valign="top" width="200"><a title="Passion" href="http://www.flickr.com/photos/12744616@N08/2856230315/"><img alt="Passion" src="http://static.flickr.com/3119/2856230315_996b5a98b0_t.jpg" align="middle" border="0" /></a></td>
</tr>
</tbody>
</table>
<p>Saturday morning there was a common session for MSPs and professionals on where Microsoft is going in the next year. After lunch, we had a bit of luck as the rain stopped and we went &quot;out in the open&quot; for some ATV, horseback riding, biking and Tyrolean traverse. Things went ok, considering it got quite cold, I had to ride a 700cc ATV with no helmet and one ATV crashed by tumbling through the air (I&#8217;m not kidding) and into someone&#8217;s yard, but no one got (seriously) hurt.</p>
<p>In the evening, we had a few games of <a href="http://en.wikipedia.org/wiki/Mafia_(party_game)" target="_blank">Mafia</a>. It&#8217;s quite a tradition at the Community Bootcamp, possibly because there&#8217;s never a shortage in supply of great players. It was my first time playing the game and I enjoyed it.</p>
<p>On the last day, each team had a private talk with the academic program leader, Todi. After that, we had lunch and went home tired, but (at least a bit) happier&#8230;</p>
<p>The main attraction for (part) of our university&#8217;s team were the squirrels in the park near our hotel. Apparently all Romanian squirrels answer to the name of Mariana, and they come to feed if you start making noise by knocking 2 nuts against each other. I can say that the squirrels respond well to food, as for the Mariana part&#8230; I&#8217;m not so convinced. Or maybe it&#8217;s (somehow) my fault that they wouldn&#8217;t answer my calls.</p>
<table cellspacing="0" cellpadding="2" width="400" border="1">
<tbody>
<tr>
<td valign="top" width="200"><a title="Feeding the invisible squirell" href="http://www.flickr.com/photos/12744616@N08/2857051264/"><img height="165" alt="Feeding the invisible squirell" src="http://static.flickr.com/3120/2857051264_8c482e9d62_m.jpg" width="220" border="0" /></a></td>
<td valign="top" width="200"><a title="More squirell feeding" href="http://www.flickr.com/photos/12744616@N08/2857048396/"><img height="165" alt="More squirell feeding" src="http://static.flickr.com/3100/2857048396_b29dcffb77_m.jpg" width="220" border="0" /></a></td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.lazarciuc.ro/ioan/2008/09/18/microsoft-community-bootcamp-v5/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Creating a Vista Sidebar Gadget Using Microsoft Silverlight</title>
		<link>http://www.lazarciuc.ro/ioan/2008/08/02/creating-a-vista-sidebar-gadget-using-microsoft-silverlight/</link>
		<comments>http://www.lazarciuc.ro/ioan/2008/08/02/creating-a-vista-sidebar-gadget-using-microsoft-silverlight/#comments</comments>
		<pubDate>Sat, 02 Aug 2008 14:25:53 +0000</pubDate>
		<dc:creator>cretz</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Gadget]]></category>

		<category><![CDATA[Sidebar]]></category>

		<category><![CDATA[silverlight]]></category>

		<category><![CDATA[template. visual studio]]></category>

		<guid isPermaLink="false">http://www.lazarciuc.ro/ioan/2008/08/02/creating-a-vista-sidebar-gadget-using-microsoft-silverlight/</guid>
		<description><![CDATA[Introduction
Some while ago I did a post on how to create a Vista Sidebar gadget using JavaScript. I also mentioned that I tried to create the gadget using XBAP or Silverlight, but due to the limitations in those technologies at that time, I decided that I had to give up on too much of the [...]]]></description>
			<content:encoded><![CDATA[<h3>Introduction</h3>
<p>Some while ago I did a <a title="Creating Sidebar Gadgets using JavaScript only" href="http://www.lazarciuc.ro/ioan/2007/11/01/creating-a-windows-vista-sidebar-gadget/" target="_blank">post</a> on how to create a Vista Sidebar gadget using JavaScript. I also mentioned that I tried to create the gadget using XBAP or Silverlight, but due to the limitations in those technologies at that time, I decided that I had to give up on too much of the Sidebar gadget specific functionality (flyouts, cross domain data retrieval).</p>
<p>More than 6 months have passed since then and now I am pleased to announce that I&#8217;ve changed my opinion regarding Silverlight Sidebar gadgets. Due to the fact that the Silverlight technology has matured a lot (version 2.0 beta 2 is now available), Sidebar gadgets can be developed using this technology, without sacrificing any Sidebar gadget specific functionality. This is due to the fact that there is full interoperability between Silverlight and the JavaScript code. Also, cross domain calls are now allowed in Silverlight, so retrieving data is no longer an issue. Furthermore, it has been greatly enhanced due to the fact that one can consume <a title="MSDN on Windows Communication Foundation" href="http://msdn.microsoft.com/en-us/library/ms735119.aspx" target="_blank">WCF</a> services using Silverlight.</p>
</p>
<p> <span id="more-18"></span>
</p>
<h3>Getting Started</h3>
<p>The first step is to have a look over the &quot;classic&quot; <a href="http://www.lazarciuc.ro/ioan/2007/11/01/creating-a-windows-vista-sidebar-gadget/" target="_blank">way</a> of developing Sidebar gadgets. Even though most of the &quot;hard work&quot; can now be done in Silverlight, the &quot;wiring&quot;, the guts of the whole gadget are still the classic ones, relying on JavaScript and HTML. Next, if you are not familiar with Silverlight development, I recommend you spend some time getting comfortable with Silverlight. For this you can visit <a href="http://www.silverlight.net">http://www.silverlight.net</a> and try out the tutorials there.</p>
<p>The result of my inquiries in this subject is a Visual Studio project template that can be used to quickly start development for a Silverlight Sidebar gadget. I got inspired by the template <a title="Tim Heuer&#39;s Project Tempalte for Sidebar Gadgets" href="http://timheuer.com/blog/archive/2007/03/11/14010.aspx" target="_blank">Tim Heuer</a> has created for jump starting Sidebar gadget development using just JavaScript/HTML. The requirements for installing and using the template are:</p>
<ul>
<li>Microsoft Visual Studio 2008 (Standard or better) </li>
<li>Microsoft Silverlight 2.0 beta 2 </li>
<li>Silverlight Tools Beta 2 for Visual Studio 2008 </li>
</ul>
<p>After downloading the template installer from <a title="Silverlight Sidebar Gadget Project Template Installer" href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/SilverlightSidebarGadget.vsi" target="_blank">here</a>, in order to install it, just run the downloaded file. The Visual Studio Content Installer will handle the rest (click next and ignore security warnings, because I did not sign the template).</p>
<p>After installing the template, in order to create a new Sidebar gadget, in Visual Studio click File-&gt;New-&gt;Project. You will notice that under the C# node, at the bottom, under &quot;My Templates&quot;, a new entry has appeared: &quot;Silverlight Sidebar Gadget&quot;. Give the solution a name and then click Ok.</p>
<p><a href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/CreatingaVistaSidebarGadgetUsingSilverli_DEE6/NewProject.jpg"><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="NewProject" src="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/CreatingaVistaSidebarGadgetUsingSilverli_DEE6/NewProject_thumb.jpg" width="468" height="333" /></a></p>
<p>You will notice that 6 projects have been automatically added to the newly created solution: SilverlightSidebarGadgetWeb, SilverlightGadgetDocked, SilverlightGadgetUnDocked, SilverlightGadgetSettings, SilverlightGadgetFlyout and SilverlightGadgetUtilities. In order, these correspond to: the main gadget web site project that will actually end up being deployed (all content and code is added to this site), the Silverlight control that is displayed when the gadget is docked, the Silverlight control that is displayed when the gadget is undocked, the Silverlight control that is displayed on the settings page of the gadget, the Silverlight control that is displayed on the flyout page of the gadget and a utilities library for Silverlight, providing a managed code API for Sidebar gadgets. This API translates to calls in the JavaScript Sidebar Gadget API.</p>
<p><strong>IMPORTANT:</strong> Due to limitations in the way the template is built, the Silverlight applications have to be added to the gadget&#8217;s main project manually. This can be done by going to the Property Pages for the website project, the Silverlight Applications tab and then click add for each additional Silverlight project. Clear the &quot;Add a test page that references the control&quot; checkbox, and make sure the &quot;Enable Silverlight debugging&quot;checkbox is checked if you want debugging capabilities for Silverlight. Silverlight and JavaScript simultaneous debugging is not possible at the current time (Silverlight debugging requires disabling Script debugging from IE).</p>
<p><a href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/CreatingaVistaSidebarGadgetUsingSilverli_DEE6/AddSilverlightApplications.jpg"><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="AddSilverlightApplications" src="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/CreatingaVistaSidebarGadgetUsingSilverli_DEE6/AddSilverlightApplications_thumb.jpg" width="470" height="334" /></a></p>
<p>In a later version of the project template this will no longer be required, but for that I have to add a custom Wizard to the project template that can prepare the projects in the template.</p>
<p>The code is commented, so I&#8217;m not going to cover it in detail. Also, for Sidebar gadget development guidance, read my previous <a title="Creating Sidebar Gadgets using JavaScript only" href="http://www.lazarciuc.ro/ioan/2007/11/01/creating-a-windows-vista-sidebar-gadget/" target="_blank">post</a> on the topic. The gadget is set up to use Silverlight controls for each page of the gadget. This is not required, and Silverlight controls can be removed from the project (along with their projects form the solution) as needed. There are 2 main classes defined in the SilverlightGadgetUtilities class: SilverlightGadget and SilverlightGadgetEvents. The first is used to access the JavaScript Sidebar Gadget API. The second is used to expose the JavaScript events related to a gadget as managed events in the Silverlight controls.</p>
<h3>Known &quot;bumps&quot;</h3>
<p>There are some things that will simply not work, no matter how hard you try to get them to work. Usually this is due to the fact that the current Sidebar gadget API or the gadget user experience provided by Microsoft does not allow it. These &quot;hick-ups&quot; are specified in the documentation comments of the classes or directly as comments.</p>
<p>Due to the fact that the Gadget JavaScript object does not allow attaching multiple event handlers for the same event, one must take care what event handler is registered for a particular event. Possible outcomes are: events that do not get triggered at all in the Silverlight controls, events that get triggered only in some Silverlight controls.</p>
<p>Due to the user experience with Sidebar gadgets, some events cannot be triggered in Silverlight controls: the Docked, Undocked events, all gadget events in the flyout, etc.</p>
<p>Some properties from the SilverlightGadget class are read-only even though the Sidebar gadget JavaScript API specifies that they are read-write. This is due to the fact that attempting to set those properties resulted in exceptions at runtime and those exceptions are most probably caused by the JavaScript API itself.</p>
<p>I tried to &quot;discover&quot; all such &quot;bumps&quot; that might appear and document them in the template directly. If there is something I missed or you have a question, please <a href="http://www.lazarciuc.ro/ioan/contact/" target="_blank">contact me</a> or post a comment and I will try to modify the template to fix or document the issue. Also, any suggestions on improving this project template are welcomed.</p>
<p>I&#8217;m looking forward to seeing many Silverlight Sidebar gadgets being developed. If you create such a gadget using this project template, please let me know by posting a comment with a link to the Live Gallery page of the gadget or a link to a page describing it.</p>
<p>Once again, the link for the Visual Studio project template is displayed below.</p>
<p>FILE: <a href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/SilverlightSidebarGadget.vsi" target="_blank">SilverlightSidebarGadget.vsi</a></p>
<p><strong>UPDATE: </strong>If you have Microsoft Visual Studio 2008 SP1 installed, you will need the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=50A9EC01-267B-4521-B7D7-C0DBA8866434&amp;displaylang=en" target="_blank">Microsoft Visual Studio Tools Beta 2 for Visual Studio 2008</a> in order to be able to create Silverlight projects. This also means that you cannot use the provided template without installing the new version of the Silverlight Tools.</p>
<p><strong>UPDATE 2:</strong> I’ve upgraded the projects in the template for Silverlight 3 Beta. The corresponding template can be found <a href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/SilverlightSidebarGadget_3Beta.vsi" target="_blank">here</a>.</p>
<p><strong>UPDATE 3:</strong> I’ve created a version of the template for Silverlight 2 final. The corresponding template can be found <a href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/SilverlightSidebarGadget_2.vsi" target="_blank">here</a>.</p>
<p><strong>UPDATE 4:</strong> I’ve upgraded the projects in the template for Silverlight 3 RTW. The corresponding template can be found <a href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2009/SilverlightSidebarGadget_3RTW.vsi" target="_blank">here</a>.</p>
<p><strong>UPDATE 5:</strong> I’ve created a version of the template using Visual Basic projects. The corresponding template can be found <a href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2009/SilverlightSidebarGadget_3RTW_vb.vsi" target="_blank">here</a>.</p>
<p><strong>UPDATE 6:</strong> I’ve created a version of the template for Visual Studio 2010, using the new extension format. The corresponding template can be found <a href="http://visualstudiogallery.msdn.microsoft.com/en-us/bf347eb6-99bd-4c99-89d0-6ca3fe1eb54e" target="_blank">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lazarciuc.ro/ioan/2008/08/02/creating-a-vista-sidebar-gadget-using-microsoft-silverlight/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Auto Complete for Textboxes in WPF</title>
		<link>http://www.lazarciuc.ro/ioan/2008/06/01/auto-complete-for-textboxes-in-wpf/</link>
		<comments>http://www.lazarciuc.ro/ioan/2008/06/01/auto-complete-for-textboxes-in-wpf/#comments</comments>
		<pubDate>Sun, 01 Jun 2008 16:05:14 +0000</pubDate>
		<dc:creator>cretz</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[auto complete. textbox]]></category>

		<category><![CDATA[wpf]]></category>

		<guid isPermaLink="false">http://www.lazarciuc.ro/ioan/2008/06/01/auto-complete-for-textboxes-in-wpf/</guid>
		<description><![CDATA[
Introduction
It is very common when entering a search string in a textbox to get a small list of valid search results that match the search string entered so far. This feature is called auto complete and it has been widely used in web pages and desktop applications alike.
From the developer&#8217;s point of view, the auto [...]]]></description>
			<content:encoded><![CDATA[<h3></h3>
<h3>Introduction</h3>
<p>It is very common when entering a search string in a textbox to get a small list of valid search results that match the search string entered so far. This feature is called auto complete and it has been widely used in web pages and desktop applications alike.</p>
<p>From the developer&#8217;s point of view, the auto complete feature has been implemented as part of the <a title="TextBox auto complete functionality" href="http://msdn.microsoft.com/en-us/library/system.windows.forms.textbox.autocompletemode(VS.85).aspx" target="_blank">TextBox</a> control in Windows Forms. That being said, I had a bit of a surprise when I could not find the functionality in the Windows Presentation Foundation <a title="WPF TextBox Members" href="http://msdn.microsoft.com/en-us/library/system.windows.controls.textbox_members.aspx" target="_blank">TextBox</a> control. Upon further online searches on the matter, I discovered that, in fact, auto complete has not been implemented for textboxes in WPF. The purpose of this post is to suggest (no pun intended) an implementation for the missing feature.</p>
<h3>Functional Description</h3>
<p>The entity we wish to create is a WPF user control that can be instantiated both through Xaml and code (C# or VB). We can either inherit from TextBox and add properties and methods required for auto complete, or we can create a control that can &quot;wire up&quot; the auto complete feature for any targeted TextBox control. The first approach not recommended due to the fact that a ListBox must be added to a TextBox. I chose to follow the second approach, perhaps being inspired by the AutoCompleteExtender in the ASP.NET AJAX Control Toolkit and also because it requires minimum intervention on existing WPF code (no need to change the type of many TextBox controls). Also, I did not include the targeted TextBox inside the custom control, in order to be able to apply this functionality on already existing code. The variant with the TextBox included can be found <a title="AskErnest.com auto complete implementation" href="http://askernest.com/archive/2008/01/23/how-to-make-a-basic-autocomplete-textbox-using-wpf.aspx" target="_blank">here</a>.</p>
<p>A finite number of suggestions should be displayed as soon as a minimum number of&#160; characters are typed, and then the suggestion list should be updated with each new modification to the search string. The maximum number of suggestions displayed should be configurable by means of a property. The user should be able to highlight a suggestion using the up/down keys, and be able to select a suggestion by pressing Tab or Enter in order to set the text of the target TextBox to that value. The means by which the suggestions are returned (from a web service, or simple method, etc.) should be as configurable as possible.</p>
<p> <span id="more-17"></span>
</p>
<h3>Implementation</h3>
<p>The starting point for the TextBoxAutoCompleteProvider is a <a title="MSDN on UserControl" href="http://msdn.microsoft.com/en-us/library/system.windows.controls.usercontrol.aspx" target="_blank">UserControl</a>. This control will contain a <a title="MSDN on Popup" href="http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.popup.aspx" target="_blank">Popup</a> (named pop) and a <a title="MSDN on ListBox" href="http://msdn.microsoft.com/en-us/library/system.windows.controls.listbox.aspx" target="_blank">ListBox</a> (named lstBox) inside the Popup. the Popup is used to hide and show the suggestions list next to the targeted TextBox.</p>
<p>The control will use <a title="MSDN on Dependency Properties" href="http://msdn.microsoft.com/en-us/library/ms752914.aspx" target="_blank">dependency properties</a> instead of classic properties in order to facilitate data binding. It will also implement the <a title="MSDN on INotifyPropertyChanged" href="http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(VS.80).aspx" target="_blank">INotifyPropertyChanged</a> interface in order to automatically update data bindings. A <a title="MSDN on Routed Events" href="http://msdn.microsoft.com/en-us/library/ms742806.aspx" target="_blank">routed event</a> named SelectionChanged is defined in order to be raised every time the selected suggestion changes.</p>
<p>The DisplayMemberPath and SelectedValuePath are strings representing properties available in the objects returned as suggestions. If the strings are empty or null, then the ToString method will be used. The SelectedItem and SelectedValue properties connect directly to their namesakes from the ListBox. The MovesFocus property determines whether the focus changes to the next control after selecting a suggestion. The MinTypedCharacters property sets the minimum length of the search string in order to start displaying suggestions. MaxResults controls the maximum number of suggestions to be displayed and AvailableSuggestions shows the number of suggestions currently displayed in the ListBox (it might be smaller than MaxResults).</p>
<p>SearchMethod is a delegate of type AutoCompleteEventHandler, used to store the method that will be called in order to obtain suggestions. The delegate signature takes the search string and the maximum number of results as parameters and returns a collection of objects. In order to be as least restrictive as possible, the type of collection returned is IEnumerable. By using a delegate, the source of the data behind the suggestions can be arbitrary (database, web service, memory objects, etc.).</p>
<p>The main property of the control is TargetControl, of type TextBox. Whenever the value of the property changes, the event handlers are removed from the old TextBox and added to the new one. The code for those event handlers, together with the code that makes the changes is displayed below.</p>
<div style="border-bottom: gray 1px solid; border-left: gray 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; max-height: 200px; font-size: 8pt; overflow: auto; border-top: gray 1px solid; cursor: text; border-right: gray 1px solid; padding-top: 4px">
<div style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px">
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> TargetControl_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   2:</span>         {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   3:</span>             <span style="color: #0000ff">if</span> (e.OldValue != e.NewValue)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   4:</span>             {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   5:</span>                 TextBoxAutoCompleteProvider me = d <span style="color: #0000ff">as</span> TextBoxAutoCompleteProvider;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   6:</span>                 TextBox oldv = e.OldValue <span style="color: #0000ff">as</span> TextBox;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   7:</span>                 TextBox newv = e.NewValue <span style="color: #0000ff">as</span> TextBox;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   8:</span>                 <span style="color: #0000ff">if</span> (oldv != <span style="color: #0000ff">null</span>)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">   9:</span>                 {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  10:</span>                     oldv.LostFocus -= <span style="color: #0000ff">new</span> RoutedEventHandler(me.TargetControl_LostFocus);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  11:</span>                     oldv.GotFocus -= <span style="color: #0000ff">new</span> RoutedEventHandler(me.TargetControl_GotFocus);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  12:</span>                     oldv.KeyUp -= <span style="color: #0000ff">new</span> KeyEventHandler(me.TargetControl_KeyUp);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  13:</span>                     oldv.PreviewKeyUp -= <span style="color: #0000ff">new</span> KeyEventHandler(me.TargetControl_PreviewKeyUp);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  14:</span>                     oldv.PreviewKeyDown -= <span style="color: #0000ff">new</span> KeyEventHandler(me.TargetControl_PreviewKeyDown);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  15:</span>                     </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  16:</span>                 }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  17:</span>                 <span style="color: #0000ff">if</span> (newv != <span style="color: #0000ff">null</span>)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  18:</span>                 {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  19:</span>                     me.pop.PlacementTarget = newv;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  20:</span>                     newv.LostFocus += <span style="color: #0000ff">new</span> RoutedEventHandler(me.TargetControl_LostFocus);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  21:</span>                     newv.GotFocus += <span style="color: #0000ff">new</span> RoutedEventHandler(me.TargetControl_GotFocus);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  22:</span>                     newv.KeyUp += <span style="color: #0000ff">new</span> KeyEventHandler(me.TargetControl_KeyUp);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  23:</span>                     newv.PreviewKeyUp += <span style="color: #0000ff">new</span> KeyEventHandler(me.TargetControl_PreviewKeyUp);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  24:</span>                     newv.PreviewKeyDown += <span style="color: #0000ff">new</span> KeyEventHandler(me.TargetControl_PreviewKeyDown);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  25:</span>                 }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  26:</span>             }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  27:</span>         }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  28:</span>&#160; </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  29:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> TargetControl_PreviewKeyDown(<span style="color: #0000ff">object</span> sender, KeyEventArgs e)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  30:</span>         {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  31:</span>             <span style="color: #0000ff">if</span> (e.Key == Key.Tab &amp;&amp; lstBox.SelectedItem != <span style="color: #0000ff">null</span>)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  32:</span>             {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  33:</span>                 pop.IsOpen = <span style="color: #0000ff">false</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  34:</span>                 TargetControl.Text = String.IsNullOrEmpty(DisplayMemberPath) ?</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  35:</span>                                      lstBox.SelectedItem.ToString() :</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  36:</span>                                      lstBox.SelectedItem.GetType().GetProperty(</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  37:</span>                                      DisplayMemberPath).GetValue(lstBox.SelectedItem, <span style="color: #0000ff">null</span>).ToString();</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  38:</span>                 <span style="color: #0000ff">if</span> (MovesFocus)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  39:</span>                     TargetControl.MoveFocus(<span style="color: #0000ff">new</span> TraversalRequest(FocusNavigationDirection.Next));</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  40:</span>                 e.Handled = <span style="color: #0000ff">true</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  41:</span>             }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  42:</span>         }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  43:</span>&#160; </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  44:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> TargetControl_PreviewKeyUp(<span style="color: #0000ff">object</span> sender, KeyEventArgs e)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  45:</span>         {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  46:</span>             <span style="color: #0000ff">if</span> (e.Key == Key.Escape)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  47:</span>             {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  48:</span>                 pop.IsOpen = <span style="color: #0000ff">false</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  49:</span>                 lstBox.SelectedItem = <span style="color: #0000ff">null</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  50:</span>                 e.Handled = <span style="color: #0000ff">true</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  51:</span>             }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  52:</span>             <span style="color: #0000ff">if</span> (IsTextChangingKey(e.Key))</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  53:</span>             {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  54:</span>                 Suggest();</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  55:</span>             }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  56:</span>         }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  57:</span>&#160; </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  58:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">bool</span> IsTextChangingKey(Key key)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  59:</span>         {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  60:</span>             <span style="color: #0000ff">if</span> (key == Key.Back || key == Key.Delete)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  61:</span>                 <span style="color: #0000ff">return</span> <span style="color: #0000ff">true</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  62:</span>             <span style="color: #0000ff">else</span></pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  63:</span>             {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  64:</span>                 KeyConverter conv = <span style="color: #0000ff">new</span> KeyConverter();</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  65:</span>                 <span style="color: #0000ff">string</span> keyString = (<span style="color: #0000ff">string</span>)conv.ConvertTo(key, <span style="color: #0000ff">typeof</span>(<span style="color: #0000ff">string</span>));</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  66:</span>&#160; </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  67:</span>                 <span style="color: #0000ff">return</span> keyString.Length == 1;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  68:</span>             }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  69:</span>         }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  70:</span>&#160; </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  71:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> TargetControl_KeyUp(<span style="color: #0000ff">object</span> sender, KeyEventArgs e)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  72:</span>         {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  73:</span>             <span style="color: #0000ff">if</span> (e.Key == Key.Up)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  74:</span>             {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  75:</span>                 <span style="color: #0000ff">if</span> (lstBox.SelectedIndex &gt; 0)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  76:</span>                 {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  77:</span>                     lstBox.SelectedIndex--;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  78:</span>                 }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  79:</span>             }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  80:</span>             <span style="color: #0000ff">if</span> (e.Key == Key.Down)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  81:</span>             {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  82:</span>                 <span style="color: #0000ff">if</span> (lstBox.SelectedIndex &lt; lstBox.Items.Count - 1)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  83:</span>                 {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  84:</span>                     lstBox.SelectedIndex++;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  85:</span>                 }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  86:</span>             }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  87:</span>             <span style="color: #0000ff">if</span> (e.Key == Key.Enter)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  88:</span>             {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  89:</span>                 SetTextAndHide();</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  90:</span>             }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  91:</span>         }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  92:</span>&#160; </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  93:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> SetTextAndHide()</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  94:</span>         {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  95:</span>             pop.IsOpen = <span style="color: #0000ff">false</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  96:</span>             <span style="color: #0000ff">if</span> (lstBox.SelectedItem != <span style="color: #0000ff">null</span>)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  97:</span>             {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  98:</span>                 TargetControl.Text = String.IsNullOrEmpty(DisplayMemberPath) ?</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060">  99:</span>                                      lstBox.SelectedItem.ToString() :</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 100:</span>                                      lstBox.SelectedItem.GetType().GetProperty(</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 101:</span>                                         DisplayMemberPath).GetValue(lstBox.SelectedItem, <span style="color: #0000ff">null</span>).ToString();</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 102:</span>                 itemsSelected = <span style="color: #0000ff">true</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 103:</span>                 <span style="color: #0000ff">if</span> (MovesFocus)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 104:</span>                     TargetControl.MoveFocus(<span style="color: #0000ff">new</span> TraversalRequest(FocusNavigationDirection.Next));</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 105:</span>             }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 106:</span>         }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 107:</span>&#160; </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 108:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> TargetControl_GotFocus(<span style="color: #0000ff">object</span> sender, RoutedEventArgs e)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 109:</span>         {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 110:</span>             <span style="color: #0000ff">if</span> (itemsSelected)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 111:</span>                 itemsSelected = <span style="color: #0000ff">false</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 112:</span>             <span style="color: #0000ff">else</span> Suggest();</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 113:</span>         }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 114:</span>&#160; </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 115:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> TargetControl_LostFocus(<span style="color: #0000ff">object</span> sender, RoutedEventArgs e)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 116:</span>         {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 117:</span>             <span style="color: #0000ff">if</span> (!pop.IsKeyboardFocusWithin)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 118:</span>                 pop.IsOpen = <span style="color: #0000ff">false</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 119:</span>         }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 120:</span>&#160; </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 121:</span>         <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> Suggest()</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 122:</span>         {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 123:</span>             <span style="color: #008000">// Skip if TargetControl are not defined or if not enough characters typed</span></pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 124:</span>             <span style="color: #0000ff">if</span> (TargetControl == <span style="color: #0000ff">null</span>) <span style="color: #0000ff">return</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 125:</span>             <span style="color: #0000ff">if</span> (TargetControl.Text.Length &lt; MinTypedCharacters)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 126:</span>             {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 127:</span>                 pop.IsOpen = <span style="color: #0000ff">false</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 128:</span>                 lstBox.ItemsSource = <span style="color: #0000ff">null</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 129:</span>                 <span style="color: #0000ff">return</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 130:</span>             }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 131:</span>             <span style="color: #0000ff">if</span> (SearchMethod == <span style="color: #0000ff">null</span>) <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> NullReferenceException(<span style="color: #006080">&quot;SeachMethod cannot be null.&quot;</span>);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 132:</span>&#160; </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 133:</span>             IEnumerable res = SearchMethod(TargetControl.Text, MaxResults);</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 134:</span>&#160; </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 135:</span>             lstBox.ItemsSource = res;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 136:</span>             <span style="color: #0000ff">if</span> (lstBox.Items.Count &gt; 0)</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 137:</span>             {</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 138:</span>                 lstBox.SelectedIndex = 0;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 139:</span>             }</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 140:</span>&#160; </pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 141:</span>             pop.VerticalOffset = TargetControl.ActualHeight;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 142:</span>             pop.IsOpen = <span style="color: #0000ff">true</span>;</pre>
<pre style="border-bottom-style: none; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: consolas, &#39;Courier New&#39;, courier, monospace; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060"> 143:</span>         }</pre>
</p></div>
</div>
<p>The private Suggest method gets called whenever the targeted TextBox receives the input focus, or the search string has changed as a result of user input. This method is responsible for invoking the method stored in the SearchMethod delegate if some conditions are met (minimum number of characters, Search method and TargetControl specified).</p>
<p>When a suggestion is selected (either by pressing Enter, Tab or by using the mouse), reflection is used to obtain the value of the property specified by DisplayMemberPath within the SelectedItem and to set the Text of the TextBox to this value. If DisplayMemberPath is empty or null, then the ToString method is used to fill in the TextBox.</p>
<p>The other properties defined by TextBoxAutoCompleteProvider offer customization options for the list of suggestions (ItemTemplate, ItemTemplateSelector, ItemsPanel).</p>
<p>Source code for the whole project, as well as a sample application can be found <a title="Source Code" href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/WPFAutoComplete.zip" target="_blank">here</a>.</p>
<h3>Conclusion</h3>
<p>The auto complete functionality is not difficult to implement, and by not extending the functionality of TextBox, applying auto complete to new and existing projects is easy. The only restriction is that one cannot specify the method to store in the SeachMethod delegate from Xaml code, only from C#(or VB.NET). Further development can be targeted at providing more customization properties for the suggestion list and at creating a converter from string to a delegate, in order to be able to specify the search method from Xaml code.</p>
<h3>Update</h3>
<p>After the feeback provided, I changed the control to allow selecting an option in the ListBox through mouse clicks. The new source code is available <a title="Source Code" href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/WPFAutoCompleteNew.zip" target="_blank">here</a>. Tracking the position of the target control is not supported for the Popup control. An adorner would have to be used for this. If I find the time to redesign the control to use adorners, then I will publish the update.</p>
<h3></h3>
</p>
<h3>Update 2</h3>
<p>After Harry’s comment, I fixed a bug that would reset the SelectedIndex property on the list box. Also I exposed the SelectedIndex property. The new source code is available <a href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/WPFAutoCompleteNew2.zip" target="_blank">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lazarciuc.ro/ioan/2008/06/01/auto-complete-for-textboxes-in-wpf/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Managing &#34;Global Constants&#34; with a Database</title>
		<link>http://www.lazarciuc.ro/ioan/2008/01/20/managing-global-constants-with-a-database/</link>
		<comments>http://www.lazarciuc.ro/ioan/2008/01/20/managing-global-constants-with-a-database/#comments</comments>
		<pubDate>Sun, 20 Jan 2008 00:31:33 +0000</pubDate>
		<dc:creator>cretz</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[c#]]></category>

		<category><![CDATA[database constants]]></category>

		<category><![CDATA[global constants]]></category>

		<category><![CDATA[global variables]]></category>

		<guid isPermaLink="false">http://www.lazarciuc.ro/ioan/2008/01/20/managing-global-constants-with-a-database/</guid>
		<description><![CDATA[
Introduction
There always comes a time while developing an application when a programmer has to introduce some &#8220;constants&#8221;. These may be Id&#8217;s, names, time intervals. The first action is to just put the literal constant where it&#8217;s needed first.
Once the value of the constant is needed in additional places, a decision has to made: where to [...]]]></description>
			<content:encoded><![CDATA[<h1></h1>
<h3>Introduction</h3>
<p>There always comes a time while developing an application when a programmer has to introduce some &#8220;constants&#8221;. These may be Id&#8217;s, names, time intervals. The first action is to just put the literal constant where it&#8217;s needed first.</p>
<p>Once the value of the constant is needed in additional places, a decision has to made: where to store the &#8220;constant&#8221;. The really bad answer would be to just reuse the literal constant. A better approach would be to create a &#8220;const&#8221; or &#8220;readonly&#8221; field with the required value. This is perfectly fine if the constant has a very little chance of changing it&#8217;s value (due to specifications change some of the constants may change). Changes to constants defined in this way can only be performed by recompiling the code and redistributing the new build.</p>
<p>Sometimes the probability of change for a &#8220;constant&#8221; is so high, that it actually becomes a &#8220;global variable&#8221; (even though it may continue to be called a &#8220;constant&#8221;). Recompiling the whole solution now becomes unfeasible.</p>
<p><span id="more-16"></span><br />
In the following, I will propose a pattern to apply to some of these &#8220;unstable&#8221; &#8220;global constants&#8221;. I am referring to the constants that have a high probability of change and change only though one mechanism: by changing the requirements (for example, the maximum time interval during which a response for a client request must be sent). In other words, the application only reads the value of the constant.
</p>
<p>The basic idea is to have a static class that holds all such &#8220;constants&#8221; either as fields or as properties. The values for the fields or properties should be loaded from a &#8220;source&#8221; before any of the constants are used. This source can be a file, a database, a web service, etc. The advantages of choosing a remote source for the values of the constants is that the application does not have to be versioned (have it&#8217;s version number increased and redistributed) just because a few constant values have changed. I will demonstrate the use of a SQL Server database table as a source for values.</p>
<p>The code for this article is written in C#, but it can easily be adapted to any .NET language. The required tools are Microsoft Visual Studio 2005 and SQL Server. &#8220;Express&#8221; versions of the two tools are the minimum required. The source code for the article can be found <a title="Article Source Code" href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/DatabaseConstants.zip" target="_blank">here</a>. The solution was written in Visual Studio 2008. If you wish to use Visual Studio 2005, you can open the project file (.csproj) instead of the solution file (.sln).</p>
<p>The testing environment is simple: just a console application that prints the values of the defined constants. The constants are held in the GlobalConstants class.</p>
<div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4">
<div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"><span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Main(<span style="color: #0000ff">string</span>[] args)</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">{</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    Console.WriteLine(<span style="color: #006080">"String constant value is {0}"</span>, GlobalConstants.StringProperty);</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    Console.WriteLine(<span style="color: #006080">"Numerical constant value is {0}"</span>, GlobalConstants.NumericalProperty);</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    Console.WriteLine(<span style="color: #006080">"DateTime constant value is {0}"</span>,GlobalConstants.DateTimeField);</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">}</pre>
</div>
</div>
<p></p>
<p></p>
<h3>Database Setup</h3>
<p>The SQL Server Express database used is named ConstDatabase and is included with the project. The constant values are stored in the table ConstantTable. Each property has a Name(string), a Value(string) and a <a title="GUID definition" href="http://msdn2.microsoft.com/en-us/library/system.guid.aspx" target="_blank">GUID</a> (global unique identifier). The values are stored as strings and later converted into the required formats in the application. The GUIDs are used in order to refer to a constant in a &#8220;name independent&#8221; way. Also, the GUIDs avoid collisions with other identically named constants that may appear (when using several constant classes).</p>
<p>NOTE: You may need to change the connection string for the database from the one found in the source code archive.</p>
<h3>Application Constant Initialization</h3>
<p>We make use of a <a title="Tudor Vlad on Static Constructors" href="http://www.tudorvlad.ro/2007/08/18/static-constructors-populating-static-collections/" target="_blank">static constructor</a> in order to ensure that the values of the constants are retrieved as soon as the class is loaded. The main idea is to set the value of the field(property) to the one found in the ConstantTable in the row that has a matching GUID. For this we need to map each field(property) to a GUID. A good way to do this is to create and use a custom <a title="Metadata Using Attributes" href="http://msdn2.microsoft.com/en-us/library/5x6cd29c.aspx" target="_blank">attribute</a>. The declarations of the constants would look like this:</p>
<div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4">
<div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"><span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">string</span> _stringProperty = <span style="color: #006080">"Default Value"</span>;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">&nbsp;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">[DatabaseConstant(<span style="color: #006080">"bfd5bf83-ed8a-4bcc-bbca-c97bf1b89182"</span>)]</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">string</span> StringProperty</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">{</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    get { <span style="color: #0000ff">return</span> _stringProperty; }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    set { _stringProperty = <span style="color: #0000ff">value</span>; }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">}</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">&nbsp;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">decimal</span> _numericalProperty = -1.0M;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">&nbsp;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">[DatabaseConstant(<span style="color: #006080">"e3a68ed7-5a7a-4987-b53e-bc61d04efa96"</span>)]</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">decimal</span> NumericalProperty</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">{</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    get { <span style="color: #0000ff">return</span> _numericalProperty; }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    set { _numericalProperty = <span style="color: #0000ff">value</span>; }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">}</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">&nbsp;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">[DatabaseConstant(<span style="color: #006080">"821b8fcb-d052-4039-967f-aa89229dcb95"</span>)]</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> DateTime DateTimeField = <span style="color: #0000ff">new</span> DateTime();</pre>
</div>
</div>
<p>The DatabaseConstant attribute receives a GUID either as a string or a Guid .NET structure. The point is to have the static constructor &#8220;look&#8221; at each field and property that the class defines and, for the ones that have the DatabaseConstant attribute applied, get the value from the database, convert it to the proper .NET type and store it in the field (property).</p>
<p>The code for the custom attribute can be found in the archive containing the whole <a title="Article Source Code" href="http://www.lazarciuc.ro/ioan/wp-content/uploads/2008/DatabaseConstants.zip" target="_blank">source code</a> for this article.</p>
<p>Note that, even though I mentioned that the values do not change in the application code, we need setters for the properties in order to be able to set the values from the database.</p>
<p>The static constructor uses reflection in order to get all the fields and properties that have the DatabaseConstant attribute applied and to set the values. The ChangeType method of the Convert class is used to convert the string value returned by the database to the type of the property, without specifying each conversion using a switch depending on the data type of the field (property).</p>
<div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, 'Courier New', courier, monospace; background-color: #f4f4f4">
<div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"><span style="color: #0000ff">static</span> GlobalConstants()</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">{</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    StringBuilder errors = <span style="color: #0000ff">new</span> StringBuilder();</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    <span style="color: #0000ff">try</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    {</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">        FieldInfo[] fiarr = <span style="color: #0000ff">typeof</span>(GlobalConstants).GetFields();</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">        <span style="color: #0000ff">foreach</span> (FieldInfo fi <span style="color: #0000ff">in</span> fiarr)</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">        {</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">            <span style="color: #0000ff">try</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">            {</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">                <span style="color: #008000">// Iterate through all the Attributes for each field.</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">                <span style="color: #0000ff">foreach</span> (Attribute attr <span style="color: #0000ff">in</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">                    Attribute.GetCustomAttributes(fi))</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">                {</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">                    <span style="color: #008000">// Check for the DatabaseConstant attribute.</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">                    DatabaseConstantAttribute atr = attr <span style="color: #0000ff">as</span> DatabaseConstantAttribute;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">                    <span style="color: #0000ff">if</span> (atr != <span style="color: #0000ff">null</span>)</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">                    {</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">                        <span style="color: #0000ff">string</span> cVal = GetDatabaseConstantValue(atr.GUID);</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">                        fi.SetValue(<span style="color: #0000ff">null</span>, Convert.ChangeType(cVal, fi.FieldType));</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">                    }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">                }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">            }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">            <span style="color: #0000ff">catch</span> (Exception)</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">            {</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">                <span style="color: #008000">// fallback action</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">                errors.AppendFormat(<span style="color: #006080">"Could not initialize constant {0} from the database. Fallback used.\n"</span>,</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">                                    fi.Name);</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">            }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">&nbsp;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">        }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    <span style="color: #0000ff">catch</span> (Exception)</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    {</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">        <span style="color: #008000">// fallback action</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">        Console.WriteLine(<span style="color: #006080">"Could not initialize constants from database. Fallback values used."</span>);</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    <span style="color: #0000ff">if</span> (errors.Length &gt; 0)</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    {</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">        <span style="color: #008000">// log the errors</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">        Console.Write(errors);</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, 'Courier New', courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">}</pre>
</div>
</div>
<p style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: #000000; border-top-style: none; line-height: 12pt; padding-top: 0px">&nbsp;</p>
<p>Reflection significantly reduces the amount of code needed to initialize every single field/property. The code for initializing the properties is the same as for the fields, except that we call GetProperties() and use PropertyInfo instead of FieldInfo. The GetDatabaseConstantValue is a simple method that uses a query to retrieve the value for the constant based on the GUID.</p>
<h3>Error Handling</h3>
<p>The advantages of remotely initializing constants have been covered. But there is also a serious drawback: what happens if for some reason the initialization fails? The database could be offline, the string stored values can be invalid for conversion (eg. numbers). As much as possible, we should have a backup set of values that could provide minimum reliability to the application (instead of just crashing, or reporting that the application cannot continue to run). Also, a logging feature would also be welcomed.</p>
<p>To do all these, try catch blocks are added around the initialization for each field/property, and for each call to the database. If the database call throws an exception, then there might be some connectivity issues. Otherwise, most likely a conversion error occurred. these errors are accumulated in the errors StringBuilder.</p>
<p>After the constructor finishes, if there are errors, they can be logged, or, in this case, displayed in the Console. It is a good practice to make sure that no exceptions will get thrown by the static constructor.</p>
<h3>Conclusion</h3>
<p>The pattern presented above provides a quick and convenient way to initialize global constants for an application. I am perfectly aware that there are several discussions to be had regarding constant initializations (error handling, complex constants, etc.). I would welcome these discussions, as well as alternative proposals in the comments section of this post.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lazarciuc.ro/ioan/2008/01/20/managing-global-constants-with-a-database/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Iron Maiden in Romania</title>
		<link>http://www.lazarciuc.ro/ioan/2007/12/27/iron-maiden-in-romania/</link>
		<comments>http://www.lazarciuc.ro/ioan/2007/12/27/iron-maiden-in-romania/#comments</comments>
		<pubDate>Thu, 27 Dec 2007 20:28:44 +0000</pubDate>
		<dc:creator>cretz</dc:creator>
		
		<category><![CDATA[I recommend]]></category>

		<category><![CDATA[concert]]></category>

		<category><![CDATA[iron maiden]]></category>

		<guid isPermaLink="false">http://www.lazarciuc.ro/ioan/2007/12/27/iron-maiden-in-romania/</guid>
		<description><![CDATA[After about 2 years of sobbing because none of the big band names I like were even considering a visit in Romania, something finally changed. On the 4th of August 2008 Iron Maiden is coming to Romania. Tickets are very reasonably priced, so get your&#8217;s while they&#8217;re cheap and available here.
Rock on.
]]></description>
			<content:encoded><![CDATA[<p>After about 2 years of sobbing because none of the big band names I like were even considering a visit in Romania, something finally changed. On the 4th of August 2008 Iron Maiden is coming to Romania. Tickets are very reasonably priced, so get your&#8217;s while they&#8217;re cheap and available <a TARGET="_blank" HREF="http://www.myticket.ro/ro/bilete/62/detaliilocatie/iron-maiden-somewhere-back-in-time-world-tour.html#biletemyticket" TITLE="Iron Maiden ticket sales site for Romania">here</a>.</p>
<p>Rock on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lazarciuc.ro/ioan/2007/12/27/iron-maiden-in-romania/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
