<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-6259562913746865237</atom:id><lastBuildDate>Wed, 30 May 2012 14:24:23 +0000</lastBuildDate><category>Geo</category><category>styles</category><category>maps</category><category>Api</category><category>marker</category><category>label</category><category>StreetView</category><category>v3</category><title>Marc Ridey - Blog</title><description /><link>http://blog.mridey.com/</link><managingEditor>noreply@blogger.com (Marc Ridey)</managingEditor><generator>Blogger</generator><openSearch:totalResults>22</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/MRidey-Blog" /><feedburner:info uri="mridey-blog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>MRidey-Blog</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-5573028874123816866</guid><pubDate>Fri, 04 May 2012 05:13:00 +0000</pubDate><atom:updated>2012-05-04T15:13:48.951+10:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Geo</category><category domain="http://www.blogger.com/atom/ns#">maps</category><category domain="http://www.blogger.com/atom/ns#">Api</category><category domain="http://www.blogger.com/atom/ns#">v3</category><category domain="http://www.blogger.com/atom/ns#">styles</category><title>Custom maps styles using the "Styled Maps Wizard"</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HOfZq7-jInrf42zJ02ga79vOxmc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HOfZq7-jInrf42zJ02ga79vOxmc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HOfZq7-jInrf42zJ02ga79vOxmc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HOfZq7-jInrf42zJ02ga79vOxmc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;I've just been asked for help on how to create a map with the Terrain background and no roads, no labels.&lt;br /&gt;
It is very easy to do using the "Styled Maps Wizard" available here:&lt;br /&gt;
&lt;a href="http://gmaps-samples-v3.googlecode.com/svn/trunk/styledmaps/wizard/index.html"&gt;http://gmaps-samples-v3.googlecode.com/svn/trunk/styledmaps/wizard/index.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
- Click on Map in the top right&lt;br /&gt;
- Select terrain ON&lt;br /&gt;
&lt;br /&gt;
At this point you should have a map with the terrain and labels.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://maps.googleapis.com/maps/api/staticmap?center=0,0&amp;amp;zoom=2&amp;amp;format=png&amp;amp;sensor=false&amp;amp;size=640x480&amp;amp;maptype=terrain" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://maps.googleapis.com/maps/api/staticmap?center=0,0&amp;amp;zoom=2&amp;amp;format=png&amp;amp;sensor=false&amp;amp;size=640x480&amp;amp;maptype=terrain" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
- Click on "All" in the top left&lt;br /&gt;
- Click on "Visibility" -&amp;gt; Off&lt;br /&gt;
&lt;br /&gt;
At this point you should have a map with the terrain and no labels but no water either.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://maps.googleapis.com/maps/api/staticmap?center=0,0&amp;amp;zoom=2&amp;amp;format=png&amp;amp;sensor=false&amp;amp;size=640x480&amp;amp;maptype=terrain&amp;amp;style=visibility:off" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://maps.googleapis.com/maps/api/staticmap?center=0,0&amp;amp;zoom=2&amp;amp;format=png&amp;amp;sensor=false&amp;amp;size=640x480&amp;amp;maptype=terrain&amp;amp;style=visibility:off" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
- Click on Add in the top left&lt;br /&gt;
- Click on Water in the top left&lt;br /&gt;
- Click "Geometry"&lt;br /&gt;
- Click on "Visibility" -&amp;gt; On&lt;br /&gt;
&lt;br /&gt;
Now you should have a map with terrain, water and no labels.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://maps.googleapis.com/maps/api/staticmap?center=0,0&amp;amp;zoom=2&amp;amp;format=png&amp;amp;sensor=false&amp;amp;size=640x480&amp;amp;maptype=terrain&amp;amp;style=visibility:off&amp;amp;style=feature:water|element:geometry|visibility:on" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://maps.googleapis.com/maps/api/staticmap?center=0,0&amp;amp;zoom=2&amp;amp;format=png&amp;amp;sensor=false&amp;amp;size=640x480&amp;amp;maptype=terrain&amp;amp;style=visibility:off&amp;amp;style=feature:water|element:geometry|visibility:on" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
- Click on "Show JSON"&lt;br /&gt;
- It should display:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;[&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; stylers: [&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; { visibility: "off" }&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; ]&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; },{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; featureType: "water",&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; elementType: "geometry",&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; stylers: [&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; { visibility: "on" }&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; ]&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;]&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Use this value to style your map as follow:&lt;br /&gt;
&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; var map = new google.maps.Map(&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; document.getElementById('map_canvas'),&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; zoom: 8,&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; center: new google.maps.LatLng(-34.397, 150.644),&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; mapTypeId: google.maps.MapTypeId.TERRAIN,&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; styles: [&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; stylers: [&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; { visibility: "off" }&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ]&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; },{&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; featureType: "water",&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; elementType: "geometry",&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; stylers: [&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; { visibility: "on" }&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ]&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; ]&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; });&lt;/span&gt;&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Hope this helps :)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-5573028874123816866?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/oprwbyrm9Pc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/oprwbyrm9Pc/custom-maps-styles-using-styled-maps.html</link><author>noreply@blogger.com (Marc (Google Employee))</author><thr:total>0</thr:total><feedburner:origLink>http://blog.mridey.com/2012/05/custom-maps-styles-using-styled-maps.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-4863003496090810202</guid><pubDate>Tue, 04 Oct 2011 12:46:00 +0000</pubDate><atom:updated>2011-10-06T17:00:00.957+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">maps</category><category domain="http://www.blogger.com/atom/ns#">marker</category><category domain="http://www.blogger.com/atom/ns#">StreetView</category><category domain="http://www.blogger.com/atom/ns#">Api</category><category domain="http://www.blogger.com/atom/ns#">v3</category><category domain="http://www.blogger.com/atom/ns#">label</category><title>Dynamic markers in Maps API Javascript v3</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LTVZGasC1vlo3Ndqwgxvx1H-X6E/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LTVZGasC1vlo3Ndqwgxvx1H-X6E/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LTVZGasC1vlo3Ndqwgxvx1H-X6E/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LTVZGasC1vlo3Ndqwgxvx1H-X6E/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;
  Another option for labels is to use dynamic markers.&lt;br /&gt;
  These are provided by the Google Chart tools API.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;You can set the shape, color and text of each marker.&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;
  The documentation for the markers can be found at&lt;/br&gt;
  &lt;a href="http://code.google.com/apis/chart/infographics/docs/dynamic_icons.html"&gt;http://code.google.com/apis/chart/infographics/docs/dynamic_icons.html&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Here's a simple example on how to display a marker and its shadow with custom text:&lt;br /&gt;
&lt;/span&gt;
&lt;br /&gt;
&lt;pre&gt;   
   var latLng = new google.maps.LatLng(40, -100);
   var marker = new google.maps.Marker({
      position: latLng,
      draggable: true,
      map: map,
      icon: new google.maps.MarkerImage(
        "http://chart.googleapis.com/chart?chst=d_bubble_text_small&amp;amp;chld=bb|Label%20123|FF8080|000000",
        null, null, new google.maps.Point(0, 42)),
      shadow: new google.maps.MarkerImage(
        "http://chart.googleapis.com/chart?chst=d_bubble_text_small_shadow&amp;amp;chld=bb|Label%20123",
        null, null, new google.maps.Point(0, 45))
    });
&lt;/pre&gt;
&lt;br /&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;And the marker should look like this:


&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;
&lt;div id="map_canvas" style="height: 307px; width: 307px;"&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-fzLauuLiZJo/Tor_XN2gnLI/AAAAAAAAAv0/ZlsCRypr_hk/s1600/Picture+7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-fzLauuLiZJo/Tor_XN2gnLI/AAAAAAAAAv0/ZlsCRypr_hk/s1600/Picture+7.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;script src="http://maps.google.com/maps/api/js?sensor=false&amp;callback=initialize_maps" type="text/javascript"&gt;
&lt;/script&gt;
&lt;script type="text/javascript"&gt;
  function initialize_maps() {
    var latLng = new google.maps.LatLng(40, -100);

    var map = new google.maps.Map(document.getElementById('map_canvas'), {
      zoom: 5,
      center: latLng,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    var marker = new google.maps.Marker({
      position: latLng,
      draggable: true,
      map: map,
      icon: new google.maps.MarkerImage("http://chart.googleapis.com/chart?chst=d_bubble_text_small&amp;chld=bb|Label%20123|FF8080|000000", null, null, new google.maps.Point(0, 42)),
      shadow: new google.maps.MarkerImage("http://chart.googleapis.com/chart?chst=d_bubble_text_small_shadow&amp;chld=bb|Label%20123", null, null, new google.maps.Point(0, 45))
    });
  }
&lt;/script&gt;
&lt;span style="font-family: Arial, Helvetica, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-4863003496090810202?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/AieaVubCjS0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/AieaVubCjS0/dynamic-markers-in-maps-api-javascript.html</link><author>noreply@blogger.com (Marc (Google Employee))</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-fzLauuLiZJo/Tor_XN2gnLI/AAAAAAAAAv0/ZlsCRypr_hk/s72-c/Picture+7.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://blog.mridey.com/2011/10/dynamic-markers-in-maps-api-javascript.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-8883975835102133745</guid><pubDate>Sun, 22 May 2011 07:31:00 +0000</pubDate><atom:updated>2011-05-23T08:54:01.718+10:00</atom:updated><title>Label overlay example for Google Maps API v3 - Revisited</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/u96dJ0F88kHcBgdNrQqvcVOyu8g/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/u96dJ0F88kHcBgdNrQqvcVOyu8g/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/u96dJ0F88kHcBgdNrQqvcVOyu8g/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/u96dJ0F88kHcBgdNrQqvcVOyu8g/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;A while back I published a &lt;a href="http://blog.mridey.com/2009/09/label-overlay-example-for-google-maps.html"&gt;post&lt;/a&gt; showing how to add a label to a marker. I got a lot of comments on that post, in particular regarding adding support for visibility, zIndex and click event.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-lHhkoRkaH54/Tdi6YsUFDpI/AAAAAAAAAOE/Z0X38_9JMQM/s1600/Picture+2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="238" src="http://4.bp.blogspot.com/-lHhkoRkaH54/Tdi6YsUFDpI/AAAAAAAAAOE/Z0X38_9JMQM/s320/Picture+2.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
So here's a revised version. &lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;// Define the overlay, derived from google.maps.OverlayView&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;function Label(opt_options) {&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; // Initialization&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; this.setValues(opt_options);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; // Label specific&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; var span = this.span_ = document.createElement('span');&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; span.style.cssText = 'position: relative; left: -50%; top: -8px; ' +&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; 'white-space: nowrap; border: 1px solid blue; ' +&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; 'padding: 2px; background-color: white';&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; var div = this.div_ = document.createElement('div');&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; div.appendChild(span);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; div.style.cssText = 'position: absolute; display: none';&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Label.prototype = new google.maps.OverlayView;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;// Implement onAdd&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Label.prototype.onAdd = function() {&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; var pane = this.getPanes().overlayImage;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; pane.appendChild(this.div_);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; // Ensures the label is redrawn if the text or position is changed.&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; var me = this;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; this.listeners_ = [&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; google.maps.event.addListener(this, 'position_changed', function() { me.draw(); }),&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; google.maps.event.addListener(this, 'visible_changed', function() { me.draw(); }),&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; google.maps.event.addListener(this, 'clickable_changed', function() { me.draw(); }),&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; google.maps.event.addListener(this, 'text_changed', function() { me.draw(); }),&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; google.maps.event.addListener(this, 'zindex_changed', function() { me.draw(); }),&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; google.maps.event.addDomListener(this.div_, 'click', function() { &lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; if (me.get('clickable')) {&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; google.maps.event.trigger(me, 'click');&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; })&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; ];&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;// Implement onRemove&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Label.prototype.onRemove = function() {&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; this.div_.parentNode.removeChild(this.div_);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; // Label is removed from the map, stop updating its position/text.&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; for (var i = 0, I = this.listeners_.length; i &amp;lt; I; ++i) {&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; google.maps.event.removeListener(this.listeners_[i]);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;// Implement draw&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Label.prototype.draw = function() {&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; var projection = this.getProjection();&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; var position = projection.fromLatLngToDivPixel(this.get('position'));&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; var div = this.div_;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; div.style.left = position.x + 'px';&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; div.style.top = position.y + 'px';&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; var visible = this.get('visible');&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; div.style.display = visible ? 'block' : 'none';&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; var clickable = this.get('clickable');&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; this.span_.style.cursor = clickable ? 'pointer' : '';&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; var zIndex = this.get('zIndex');&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; div.style.zIndex = zIndex;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; this.span_.innerHTML = this.get('text').toString();&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
And to use it, here's a little example:&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;lt;head&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;meta http-equiv="content-type" content="text/html; charset=utf-8"&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;title&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; Label Overlay Example&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/title&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;script type="text/javascript" src="label.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;script type="text/javascript"&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; var marker;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; function initialize() {&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var latLng = new google.maps.LatLng(40, -100);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var map = new google.maps.Map(document.getElementById('map_canvas'), {&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; zoom: 5,&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; center: latLng,&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; mapTypeId: google.maps.MapTypeId.ROADMAP&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; });&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;marker = new google.maps.Marker({&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;position: latLng,&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;draggable: true,&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;zIndex: 1,&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;map: map,&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;optimized: false&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;});&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;var label = new Label({&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;map: map&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;});&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;label.bindTo('position', marker);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;label.bindTo('text', marker, 'position');&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;label.bindTo('visible', marker);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;label.bindTo('clickable', marker);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;label.bindTo('zIndex', marker);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;google.maps.event.addListener(marker, 'click', function() { alert('Marker has been clicked'); })&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;google.maps.event.addListener(label, 'click', function() { alert('Label has been clicked'); })&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; function showHideMarker() {&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;marker.setVisible(!marker.getVisible());  &lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; function pinUnpinMarker() {&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;var draggable = marker.getDraggable();&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;marker.setDraggable(!draggable);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;marker.setClickable(!draggable);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;lt;/head&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;lt;body onload="initialize()"&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;div id="map_canvas" style="height: 200px; width: 200px"&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;button type="button" onclick="showHideMarker();"&amp;gt;Show/Hide Marker&amp;lt;/button&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;button type="button" onclick="pinUnpinMarker();"&amp;gt;Pin/Unpin Marker&amp;lt;/button&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp; &amp;lt;/body&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
The label can be used on its own or bound to a marker.&lt;br /&gt;
It supports:&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;set('position', latLng);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;get('position')&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;set('text', string);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;get('text);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;set('visible', boolean);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;get('visible');&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;set('clickable', boolean);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;get('clickable');&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;set('zIndex', index);&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;get('zIndex');&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
and provides events:&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;position_changed&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;text_changed&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;visible_changed&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;clickable_changed&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;zindex_changed&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;click&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-8883975835102133745?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/9uBCp__I-hk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/9uBCp__I-hk/label-overlay-example-for-google-maps.html</link><author>noreply@blogger.com (Marc (Google Employee))</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-lHhkoRkaH54/Tdi6YsUFDpI/AAAAAAAAAOE/Z0X38_9JMQM/s72-c/Picture+2.png" height="72" width="72" /><thr:total>49</thr:total><feedburner:origLink>http://blog.mridey.com/2011/05/label-overlay-example-for-google-maps.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-8993895412612832311</guid><pubDate>Mon, 08 Nov 2010 11:49:00 +0000</pubDate><atom:updated>2010-11-08T22:49:43.559+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">maps</category><category domain="http://www.blogger.com/atom/ns#">StreetView</category><category domain="http://www.blogger.com/atom/ns#">Api</category><category domain="http://www.blogger.com/atom/ns#">v3</category><title>Using StreetViewService in Maps API Javascript v3</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/8T6zpm80Jkct7CNmAxqPajgWNt8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8T6zpm80Jkct7CNmAxqPajgWNt8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/8T6zpm80Jkct7CNmAxqPajgWNt8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8T6zpm80Jkct7CNmAxqPajgWNt8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;Based on my recent &lt;a href="http://blog.mridey.com/2010/11/maps-api-javascript-v3-multiple-markers.html"&gt;post&lt;/a&gt;, I've added code to change the content of the infowindow if the panorama we try to display doesn't exist. This needs to be done using StreetViewService as currently the StreetViewPanorama doesn't have an event or property to notify us of a failure to load a panorama.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_SECbW4uPgAM/TNfimS_pLUI/AAAAAAAAAC8/gFRl3GHMryw/s1600/Picture+7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="232" src="http://4.bp.blogspot.com/_SECbW4uPgAM/TNfimS_pLUI/AAAAAAAAAC8/gFRl3GHMryw/s320/Picture+7.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
The code that changed:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;// Create a StreetViewService to be able to check
    // if a given LatLng has a corresponding panorama.
    var service = new google.maps.StreetViewService();
    
    // Set the infowindow content and display it on marker click.
    // Use a 'pin' MVCObject as the order of the domready and marker click events is not garanteed.
    function openInfoWindow(marker) {
      title.innerHTML = marker.getTitle();
      streetview.style['visibility'] = 'hidden';
      service.getPanoramaByLocation(marker.getPosition(), 50, function(result, status) {
        if (status == google.maps.StreetViewStatus.OK) {
          pin.set("position", marker.getPosition());
          streetview.style['visibility'] = '';
        }
      })
      infowindow.open(map, marker);
    }
&lt;/pre&gt;&lt;br /&gt;
The StreetViewService (see &lt;a href="http://code.google.com/apis/maps/documentation/javascript/reference.html#StreetViewService"&gt;Reference&lt;/a&gt; and &lt;a href="http://code.google.com/apis/maps/documentation/javascript/examples/streetview-service.html"&gt;Example&lt;/a&gt;) returns a status code. If it's OK, I make the DIV that contains the StreetView panorama visible. I could have also added text.&lt;br /&gt;
&lt;br /&gt;
And the full code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&amp;lt;!DOCTYPE html&amp;gt; 
&amp;lt;html&amp;gt; 
&amp;lt;head&amp;gt; 
&amp;lt;meta name="viewport" content="initial-scale=1.0, user-scalable=no" /&amp;gt; 
&amp;lt;meta http-equiv="content-type" content="text/html; charset=UTF-8"/&amp;gt; 
&amp;lt;title&amp;gt;Google Maps JavaScript API v3 Example: Markers, Info Window and StreetView&amp;lt;/title&amp;gt; 
&amp;lt;link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" /&amp;gt; 
&amp;lt;script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"&amp;gt;&amp;lt;/script&amp;gt; 
&amp;lt;script type="text/javascript"&amp;gt; 
  function initialize() {

    // Create the map 
    // No need to specify zoom and center as we fit the map further down.
    var map = new google.maps.Map(document.getElementById("map_canvas"), {
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      streetViewControl: false
    });
 
    // Create the shared infowindow with two DIV placeholders
    // One for a text string, the other for the StreetView panorama.
    var content = document.createElement("DIV");
    var title = document.createElement("DIV");
    content.appendChild(title);
    var streetview = document.createElement("DIV");
    streetview.style.width = "200px";
    streetview.style.height = "200px";
    content.appendChild(streetview);
    var infowindow = new google.maps.InfoWindow({
      content: content
    });

    // Define the list of markers.
    // This could be generated server-side with a script creating the array.
    var markers = [
      { lat: -33.85, lng: 151.05, name: "marker 1" },
      { lat: -33.90, lng: 151.35, name: "marker 2" },
      { lat: -33.95, lng: 151.15, name: "marker 3" },
      { lat: -33.85, lng: 151.15, name: "marker 4" }
    ];

    // Create the markers
    for (index in markers) addMarker(markers[index]);
    function addMarker(data) {
      var marker = new google.maps.Marker({
        position: new google.maps.LatLng(data.lat, data.lng),
        map: map,
        title: data.name
      });
      google.maps.event.addListener(marker, "click", function() {
        openInfoWindow(marker);
      });
    }

    // Zoom and center the map to fit the markers
    // This logic could be conbined with the marker creation.
    // Just keeping it separate for code clarity.
    var bounds = new google.maps.LatLngBounds();
    for (index in markers) {
      var data = markers[index];
      bounds.extend(new google.maps.LatLng(data.lat, data.lng));
    }
    map.fitBounds(bounds);

    // Handle the DOM ready event to create the StreetView panorama
    // as it can only be created once the DIV inside the infowindow is loaded in the DOM.
    var panorama = null;
    var pin = new google.maps.MVCObject();
    google.maps.event.addListenerOnce(infowindow, "domready", function() {
      panorama = new google.maps.StreetViewPanorama(streetview, {
          navigationControl: false,
          enableCloseButton: false,
          addressControl: false,
          linksControl: false,
          visible: true
      });
      panorama.bindTo("position", pin);
    });

    // Create a StreetViewService to be able to check
    // if a given LatLng has a corresponding panorama.
    var service = new google.maps.StreetViewService();
    
    // Set the infowindow content and display it on marker click.
    // Use a 'pin' MVCObject as the order of the domready and marker click events is not garanteed.
    function openInfoWindow(marker) {
      title.innerHTML = marker.getTitle();
      streetview.style['visibility'] = 'hidden';
      service.getPanoramaByLocation(marker.getPosition(), 50, function(result, status) {
        if (status == google.maps.StreetViewStatus.OK) {
          pin.set("position", marker.getPosition());
          streetview.style['visibility'] = '';
        }
      })
      infowindow.open(map, marker);
    }
  }
&amp;lt;/script&amp;gt; 
&amp;lt;/head&amp;gt; 
&amp;lt;body onload="initialize()"&amp;gt; 
  &amp;lt;div id="map_canvas"&amp;gt;&amp;lt;/div&amp;gt; 
&amp;lt;/body&amp;gt; 
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-8993895412612832311?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/2DA4woVZGyo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/2DA4woVZGyo/using-streetviewservice-in-maps-api.html</link><author>noreply@blogger.com (Marc (Google Employee))</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_SECbW4uPgAM/TNfimS_pLUI/AAAAAAAAAC8/gFRl3GHMryw/s72-c/Picture+7.png" height="72" width="72" /><thr:total>7</thr:total><feedburner:origLink>http://blog.mridey.com/2010/11/using-streetviewservice-in-maps-api.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-3602039771748607799</guid><pubDate>Mon, 08 Nov 2010 11:17:00 +0000</pubDate><atom:updated>2010-11-08T22:17:24.802+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">maps</category><category domain="http://www.blogger.com/atom/ns#">StreetView</category><category domain="http://www.blogger.com/atom/ns#">Api</category><category domain="http://www.blogger.com/atom/ns#">v3</category><title>Maps API Javascript v3 - Multiple Markers with multiple infowindows and StreetView</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4odF-w6Q8INfzR7dNRb6xIj7sD0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4odF-w6Q8INfzR7dNRb6xIj7sD0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4odF-w6Q8INfzR7dNRb6xIj7sD0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4odF-w6Q8INfzR7dNRb6xIj7sD0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;Similar to the previous post, I have a map with multiple markers but multiple InfoWindows, one per marker. When a marker is clicked, its infowindow is displayed with the marker title and the StreetView panorama at this location.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_SECbW4uPgAM/TNfb_XWbajI/AAAAAAAAAC4/yLUgutMKv9I/s1600/Picture+6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="260" src="http://1.bp.blogspot.com/_SECbW4uPgAM/TNfb_XWbajI/AAAAAAAAAC4/yLUgutMKv9I/s320/Picture+6.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
What to retain from this example:&lt;br /&gt;
&lt;br /&gt;
- How to add multiple markers to the map&lt;br /&gt;
- How to manage one InfoWindow per marker&lt;br /&gt;
- How to add the StreetView panorama as well as other text in the infowindow&lt;br /&gt;
- How to zoom the map to include all the markers&lt;br /&gt;
&lt;br /&gt;
I'll be posting another blog tomorrow showing how to use StreetViewService to detect if a panorama doesn't exist.&lt;br /&gt;
&lt;br /&gt;
Here's the code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&amp;lt;html&amp;gt; 
&amp;lt;head&amp;gt; 
&amp;lt;meta name="viewport" content="initial-scale=1.0, user-scalable=no" /&amp;gt; 
&amp;lt;meta http-equiv="content-type" content="text/html; charset=UTF-8"/&amp;gt; 
&amp;lt;title&amp;gt;Google Maps JavaScript API v3 Example: Markers, Info Window and StreetView&amp;lt;/title&amp;gt; 
&amp;lt;link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" /&amp;gt; 
&amp;lt;script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"&amp;gt;&amp;lt;/script&amp;gt; 
&amp;lt;script type="text/javascript"&amp;gt; 
  function initialize() {

    // Create the map 
    // No need to specify zoom and center as we fit the map further down.
    var map = new google.maps.Map(document.getElementById("map_canvas"), {
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      streetViewControl: false
    });
 
    // Define the list of markers.
    // This could be generated server-side with a script creating the array.
    var markers = [
      { lat: -33.85, lng: 151.05, name: "marker 1" },
      { lat: -33.90, lng: 151.10, name: "marker 2" },
      { lat: -33.95, lng: 151.15, name: "marker 3" },
      { lat: -33.85, lng: 151.15, name: "marker 4" }
    ];

    // Create the markers ad infowindows.
    for (index in markers) addMarker(markers[index]);
    function addMarker(data) {
      // Create the marker
      var marker = new google.maps.Marker({
        position: new google.maps.LatLng(data.lat, data.lng),
        map: map,
        title: data.name
      });
    
      // Create the infowindow with two DIV placeholders
      // One for a text string, the other for the StreetView panorama.
      var content = document.createElement("DIV");
      var title = document.createElement("DIV");
      title.innerHTML = data.name;
      content.appendChild(title);
      var streetview = document.createElement("DIV");
      streetview.style.width = "200px";
      streetview.style.height = "200px";
      content.appendChild(streetview);
      var infowindow = new google.maps.InfoWindow({
        content: content
      });

      // Open the infowindow on marker click
      google.maps.event.addListener(marker, "click", function() {
        infowindow.open(map, marker);
      });
    
      // Handle the DOM ready event to create the StreetView panorama
      // as it can only be created once the DIV inside the infowindow is loaded in the DOM.
      google.maps.event.addListenerOnce(infowindow, "domready", function() {
        var panorama = new google.maps.StreetViewPanorama(streetview, {
            navigationControl: false,
            enableCloseButton: false,
            addressControl: false,
            linksControl: false,
            visible: true,
            position: marker.getPosition()
        });
      });
    }

    // Zoom and center the map to fit the markers
    // This logic could be conbined with the marker creation.
    // Just keeping it separate for code clarity.
    var bounds = new google.maps.LatLngBounds();
    for (index in markers) {
      var data = markers[index];
      bounds.extend(new google.maps.LatLng(data.lat, data.lng));
    }
    map.fitBounds(bounds);
  }
&amp;lt;/script&amp;gt; 
&amp;lt;/head&amp;gt; 
&amp;lt;body onload="initialize()"&amp;gt; 
  &amp;lt;div id="map_canvas"&amp;gt;&amp;lt;/div&amp;gt; 
&amp;lt;/body&amp;gt; 
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-3602039771748607799?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/zYsLfbZB3FY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/zYsLfbZB3FY/maps-api-javascript-v3-multiple-markers_08.html</link><author>noreply@blogger.com (Marc (Google Employee))</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_SECbW4uPgAM/TNfb_XWbajI/AAAAAAAAAC4/yLUgutMKv9I/s72-c/Picture+6.png" height="72" width="72" /><thr:total>28</thr:total><feedburner:origLink>http://blog.mridey.com/2010/11/maps-api-javascript-v3-multiple-markers_08.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-3463916620923418606</guid><pubDate>Mon, 08 Nov 2010 10:45:00 +0000</pubDate><atom:updated>2010-11-08T21:45:28.849+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">maps</category><category domain="http://www.blogger.com/atom/ns#">StreetView</category><category domain="http://www.blogger.com/atom/ns#">Api</category><category domain="http://www.blogger.com/atom/ns#">v3</category><title>Maps API Javascript V3 - Multiple Markers, InfoWindow and StreetView</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/e1nZzVZjGpdfKawXSZNvzBXWXaU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/e1nZzVZjGpdfKawXSZNvzBXWXaU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/e1nZzVZjGpdfKawXSZNvzBXWXaU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/e1nZzVZjGpdfKawXSZNvzBXWXaU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;Another interesting example. For this blog, I have a map with multiple markers and a single InfoWindow shared between the markers. When a marker is clicked, the infowindow is displayed with the marker title and the StreetView panorama at this location.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_SECbW4uPgAM/TNfUdQJl1UI/AAAAAAAAACk/RgNzDvNKmxQ/s1600/Picture+4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="286" src="http://1.bp.blogspot.com/_SECbW4uPgAM/TNfUdQJl1UI/AAAAAAAAACk/RgNzDvNKmxQ/s320/Picture+4.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
What to retain from this example:&lt;br /&gt;
&lt;br /&gt;
- How to add multiple markers to the map&lt;br /&gt;
- How to share a single InfoWindow for all the markers&lt;br /&gt;
- How to add the StreetView panorama as well as other text in the infowindow&lt;br /&gt;
- How to zoom the map to include all the markers&lt;br /&gt;
&lt;br /&gt;
I'll be posting another blog tomorrow showing how to use multiple infowindows and how to use StreetViewService to detect if a panorama doesn't exist.&lt;br /&gt;
&lt;br /&gt;
Here's the code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&amp;lt;html&amp;gt; 
&amp;lt;head&amp;gt; 
&amp;lt;meta name="viewport" content="initial-scale=1.0, user-scalable=no" /&amp;gt; 
&amp;lt;meta http-equiv="content-type" content="text/html; charset=UTF-8"/&amp;gt; 
&amp;lt;title&amp;gt;Google Maps JavaScript API v3 Example: Markers, Info Window and StreetView&amp;lt;/title&amp;gt; 
&amp;lt;link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" /&amp;gt; 
&amp;lt;script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"&amp;gt;&amp;lt;/script&amp;gt; 
&amp;lt;script type="text/javascript"&amp;gt; 
  function initialize() {

    // Create the map 
    // No need to specify zoom and center as we fit the map further down.
    var map = new google.maps.Map(document.getElementById("map_canvas"), {
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      streetViewControl: false
    });
 
    // Create the shared infowindow with two DIV placeholders
    // One for a text string, the other for the StreetView panorama.
    var content = document.createElement("DIV");
    var title = document.createElement("DIV");
    content.appendChild(title);
    var streetview = document.createElement("DIV");
    streetview.style.width = "200px";
    streetview.style.height = "200px";
    content.appendChild(streetview);
    var infowindow = new google.maps.InfoWindow({
   content: content
    });

    // Define the list of markers.
    // This could be generated server-side with a script creating the array.
    var markers = [
      { lat: -33.85, lng: 151.05, name: "marker 1" },
      { lat: -33.90, lng: 151.10, name: "marker 2" },
      { lat: -33.95, lng: 151.15, name: "marker 3" },
      { lat: -33.85, lng: 151.15, name: "marker 4" }
    ];

    // Create the markers
    for (index in markers) addMarker(markers[index]);
    function addMarker(data) {
   var marker = new google.maps.Marker({
  position: new google.maps.LatLng(data.lat, data.lng),
  map: map,
        title: data.name
   });
   google.maps.event.addListener(marker, "click", function() {
  openInfoWindow(marker);
   });
    }

    // Zoom and center the map to fit the markers
    // This logic could be conbined with the marker creation.
    // Just keeping it separate for code clarity.
    var bounds = new google.maps.LatLngBounds();
    for (index in markers) {
   var data = markers[index];
   bounds.extend(new google.maps.LatLng(data.lat, data.lng));
 }
 map.fitBounds(bounds);

    // Handle the DOM ready event to create the StreetView panorama
    // as it can only be created once the DIV inside the infowindow is loaded in the DOM.
    var panorama = null;
    var pin = new google.maps.MVCObject();
    google.maps.event.addListenerOnce(infowindow, "domready", function() {
      panorama = new google.maps.StreetViewPanorama(streetview, {
       navigationControl: false,
       enableCloseButton: false,
       addressControl: false,
       linksControl: false,
       visible: true
      });
      panorama.bindTo("position", pin);
    });
    
    // Set the infowindow content and display it on marker click.
    // Use a 'pin' MVCObject as the order of the domready and marker click events is not garanteed.
    function openInfoWindow(marker) {
   title.innerHTML = marker.getTitle();
   pin.set("position", marker.getPosition());
   infowindow.open(map, marker);
    }
  }
&amp;lt;/script&amp;gt; 
&amp;lt;/head&amp;gt; 
&amp;lt;body onload="initialize()"&amp;gt; 
  &amp;lt;div id="map_canvas"&amp;gt;&amp;lt;/div&amp;gt; 
&amp;lt;/body&amp;gt; 
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-3463916620923418606?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/W7yEYSg-uXA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/W7yEYSg-uXA/maps-api-javascript-v3-multiple-markers.html</link><author>noreply@blogger.com (Marc (Google Employee))</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_SECbW4uPgAM/TNfUdQJl1UI/AAAAAAAAACk/RgNzDvNKmxQ/s72-c/Picture+4.png" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://blog.mridey.com/2010/11/maps-api-javascript-v3-multiple-markers.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-2102418542919100774</guid><pubDate>Fri, 05 Nov 2010 12:11:00 +0000</pubDate><atom:updated>2010-11-05T23:11:16.599+11:00</atom:updated><title>How to display a map inside StreetView</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HN1bRtHWrB1BII3h8zJ5Abj4zak/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HN1bRtHWrB1BII3h8zJ5Abj4zak/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HN1bRtHWrB1BII3h8zJ5Abj4zak/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HN1bRtHWrB1BII3h8zJ5Abj4zak/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;It's fairly easy to display a small map in the corner of a StreetView panorama.&lt;br /&gt;
You just need to add a small map on top of the StreetView panorama and bind it.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_SECbW4uPgAM/TNP0A4I63tI/AAAAAAAAACg/6xXtELTK6sU/s1600/Picture+3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="270" src="http://4.bp.blogspot.com/_SECbW4uPgAM/TNP0A4I63tI/AAAAAAAAACg/6xXtELTK6sU/s320/Picture+3.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&amp;lt;!DOCTYPE html&amp;gt; 
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"&amp;gt; 
&amp;lt;head&amp;gt; 
&amp;lt;meta http-equiv="content-type" content="text/html; charset=utf-8"/&amp;gt; 
&amp;lt;title&amp;gt;Google Maps JavaScript API Example: Street View with Map&amp;lt;/title&amp;gt; 
&amp;lt;link href="http://code.google.com/apis/maps/documentation/javascript/examples/standard.css" rel="stylesheet" type="text/css" /&amp;gt; 
&amp;lt;script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt; 
&amp;lt;script type="text/javascript"&amp;gt; 
 
  function initialize() {
    var panorama = new  google.maps.StreetViewPanorama(document.getElementById("pano"), {
   position: new google.maps.LatLng(42.345573,-71.098326),
   visible: true
    });
    var map = new google.maps.Map(document.getElementById("map_canvas"), {
      center: new google.maps.LatLng(42.345573,-71.098326),
      zoom: 14,
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      streetViewControl: true,
      streetView: panorama
    });

    google.maps.event.addListener(panorama, "position_changed", function() {
   map.setCenter(panorama.getPosition());
    });
  }
&amp;lt;/script&amp;gt; 
&amp;lt;/head&amp;gt; 
&amp;lt;body onload="initialize()"&amp;gt;
  &amp;lt;div style="position:absolute;"&amp;gt; 
    &amp;lt;div id="pano" style="z-index:0; width: 800px; height: 600px;"&amp;gt;&amp;lt;/div&amp;gt; 
    &amp;lt;div id="map_canvas" style="z-index:1; position:absolute; right:0px; bottom:0px; width: 200px; height: 150px"&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt; 
&amp;lt;/body&amp;gt; 
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-2102418542919100774?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/U9m2BG2tzfE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/U9m2BG2tzfE/how-to-display-map-inside-streetview.html</link><author>noreply@blogger.com (Marc (Google Employee))</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_SECbW4uPgAM/TNP0A4I63tI/AAAAAAAAACg/6xXtELTK6sU/s72-c/Picture+3.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://blog.mridey.com/2010/11/how-to-display-map-inside-streetview.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-527015495092495093</guid><pubDate>Fri, 05 Nov 2010 11:36:00 +0000</pubDate><atom:updated>2010-11-05T22:36:01.335+11:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">maps</category><category domain="http://www.blogger.com/atom/ns#">StreetView</category><category domain="http://www.blogger.com/atom/ns#">Api</category><category domain="http://www.blogger.com/atom/ns#">v3</category><title>How to embed StreetView in an infowindow</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HY6Ho77rd5LWQbCd-kgUydlLQTk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HY6Ho77rd5LWQbCd-kgUydlLQTk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HY6Ho77rd5LWQbCd-kgUydlLQTk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HY6Ho77rd5LWQbCd-kgUydlLQTk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;I've received a number of queries on how to get StreetView inside an infowindow showing the panorama of the marker bound to the infowindow.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_SECbW4uPgAM/TNPry0hit6I/AAAAAAAAACc/Wv00oU4TeIQ/s1600/Picture+1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="260" src="http://3.bp.blogspot.com/_SECbW4uPgAM/TNPry0hit6I/AAAAAAAAACc/Wv00oU4TeIQ/s320/Picture+1.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Here's a quick example.&lt;br /&gt;
Click on the marker to display the infowindow.&lt;br /&gt;
Drag the marker to get a different panorama.&lt;br /&gt;
&lt;br /&gt;
Code:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&amp;lt;html&amp;gt; 
&amp;lt;head&amp;gt; 
&amp;lt;meta name="viewport" content="initial-scale=1.0, user-scalable=no" /&amp;gt; 
&amp;lt;meta http-equiv="content-type" content="text/html; charset=UTF-8"/&amp;gt; 
&amp;lt;title&amp;gt;Google Maps JavaScript API v3 Example: Info Window with StreetView&amp;lt;/title&amp;gt; 
&amp;lt;link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" /&amp;gt; 
&amp;lt;script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"&amp;gt;&amp;lt;/script&amp;gt; 
&amp;lt;script type="text/javascript"&amp;gt; 
function initialize() {
var myLatlng = new google.maps.LatLng(-33.866943,151.195512);
var myOptions = {
zoom: 12,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
streetViewControl: false
}

var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);

var contentString = '&amp;lt;div id="content" style="width:200px;height:200px;"&amp;gt;&amp;lt;/div&amp;gt;';

var infowindow = new google.maps.InfoWindow({
content: contentString
});

var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Click Me',
draggable: true
});

google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});

var pano = null;
google.maps.event.addListener(infowindow, 'domready', function() {
if (pano != null) {
pano.unbind("position");
pano.setVisible(false);
}
pano = new google.maps.StreetViewPanorama(document.getElementById("content"), {
navigationControl: true,
navigationControlOptions: {style: google.maps.NavigationControlStyle.ANDROID},
enableCloseButton: false,
addressControl: false,
linksControl: false
});
pano.bindTo("position", marker);
pano.setVisible(true);
});

google.maps.event.addListener(infowindow, 'closeclick', function() {
pano.unbind("position");
pano.setVisible(false);
pano = null;
});

}

&amp;lt;/script&amp;gt; 
&amp;lt;/head&amp;gt; 
&amp;lt;body onload="initialize()"&amp;gt; 
&amp;lt;div id="map_canvas"&amp;gt;&amp;lt;/div&amp;gt; 
&amp;lt;/body&amp;gt; 
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-527015495092495093?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/85-tlf6e0Fw" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/85-tlf6e0Fw/how-to-embed-streetview-in-infowindow.html</link><author>noreply@blogger.com (Marc (Google Employee))</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_SECbW4uPgAM/TNPry0hit6I/AAAAAAAAACc/Wv00oU4TeIQ/s72-c/Picture+1.png" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://blog.mridey.com/2010/11/how-to-embed-streetview-in-infowindow.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-5622807421191618838</guid><pubDate>Thu, 27 May 2010 04:30:00 +0000</pubDate><atom:updated>2010-08-24T10:43:37.399+10:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Geo</category><category domain="http://www.blogger.com/atom/ns#">StreetView</category><category domain="http://www.blogger.com/atom/ns#">Api</category><category domain="http://www.blogger.com/atom/ns#">v3</category><title>How to create and display a custom Street View panorama using Maps Javascript API v3</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/TtR9c259EMreKsyRQwyMP1cFwAU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TtR9c259EMreKsyRQwyMP1cFwAU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/TtR9c259EMreKsyRQwyMP1cFwAU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TtR9c259EMreKsyRQwyMP1cFwAU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-size: 13px;"&gt;To display a custom panorama, first you need a tileset. &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class="Apple-style-span"&gt;&lt;span class="Apple-style-span" style="border-collapse: collapse; font-size: 13px;"&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;There are no restrictions to the tileset size or aspect ratio, the tile size or aspect ratio and the number of tiles used.&lt;/div&gt;&lt;div&gt;Just know that StreetView uses an equirectangular projection (&lt;a href="http://en.wikipedia.org/wiki/Equirectangular_projection" style="color: #114170;" target="_blank"&gt;http://en.wikipedia.org/wiki/&lt;wbr&gt;&lt;/wbr&gt;Equirectangular_projection&lt;/a&gt;)&lt;/div&gt;&lt;div&gt;so the panorama will be stretched to wrap exactly around a sphere horizontally and exactly half a sphere vertically. For this reason, a panorama with an aspect ratio 2:1 is best.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;There are many tools on the market to create the initial panorama. Look for &lt;a href="http://www.google.com.au/search?q=tile+stitching"&gt;tile stitching&lt;/a&gt;. Place a digital camera on a tripod, take enough pictures to cover every point of view from top to bottom, all around. Then use the stitching software to create a cylindrical projection of you panorama. If you are not covering the panorama from top to bottom, create the panorama as if you had and fill in the missing space with a neutral color.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Once you have created your original panorama and you have decided on the tile size, you need to create each version of the panorama for successive 1/2 height 1/2 width sizes until the panorama fits into one tile.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;For example, if you have a panorama of 6000 * 3000 pixels and you use a 512 * 512 tile size, you will need to create:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;- panorama 6000 * 3000 (12*6 tiles)&lt;/div&gt;&lt;div&gt;&lt;div&gt;- panorama 3000 * 1500 (6*3 tiles)&lt;/div&gt;&lt;div&gt;&lt;div&gt;- panorama 1500 * 750 (3*2 tiles)&lt;/div&gt;&lt;div&gt;&lt;div&gt;- panorama 750 * 375 (2*1 tiles)&lt;/div&gt;&lt;div&gt;&lt;div&gt;- panorama 375 * 187 (1*1 tile)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;When the tiles cover more area than the panorama, have the unused section of the right most tile replicate the left most tile, and the unused section of the bottom most tile filled with a neutral color.&lt;/div&gt;&lt;div&gt;The panorama with a single tile is zoom = 0, then 1,2,3,4 .. so in the example above, the largest panorama is zoom 4.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Once you have created the panoramas, cut them into tiles and name each tile according to its position and zoom level. The top left tile is always tile (0,0).&lt;/div&gt;&lt;div&gt;For the rest of this email, i'll assume that the naming convention used for the tiles is "panorama_z_x_y.jpg".&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Now the minimum required to display this panorama is:&lt;/div&gt;&lt;pre&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;        var panorama = new google.maps.&lt;wbr&gt;&lt;/wbr&gt;StreetViewPanorama(&lt;/div&gt;&lt;div&gt;            document.getElementById('&lt;wbr&gt;&lt;/wbr&gt;streetview')&lt;/div&gt;&lt;div&gt;        );&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;        panorama.&lt;wbr&gt;&lt;/wbr&gt;registerPanoProvider(&lt;wbr&gt;&lt;/wbr&gt;function(pano) {&lt;/div&gt;&lt;div&gt;          return {&lt;/div&gt;&lt;div&gt;            &lt;b&gt;tiles&lt;/b&gt;: {&lt;/div&gt;&lt;div&gt;              tileSize: new google.maps.Size(512, 512),&lt;/div&gt;&lt;div&gt;              worldSize: new google.maps.Size(6000, 3000),&lt;/div&gt;&lt;div&gt;              getTileUrl: function(room, zoom, x, y) {&lt;/div&gt;&lt;div&gt;                return "http://mydomain/somepath/" + room + '_' + zoom + '_' + x + '_' + y + '.jpg';&lt;/div&gt;&lt;div&gt;              }&lt;/div&gt;&lt;div&gt;          };&lt;/div&gt;&lt;div&gt;        });&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;        panorama.setPano('panorama'&lt;wbr&gt;&lt;/wbr&gt;);&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;If you want to display an address, a copyright and navigation links, the data to be returned looks like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;pre&gt;&lt;div&gt;&lt;div&gt;        var panorama = new google.maps.&lt;wbr&gt;&lt;/wbr&gt;StreetViewPanorama(&lt;/div&gt;&lt;div&gt;            document.getElementById('&lt;wbr&gt;&lt;/wbr&gt;streetview')&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new', monospace;"&gt;        );&lt;/span&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;        panorama.&lt;wbr&gt;&lt;/wbr&gt;registerPanoProvider(&lt;wbr&gt;&lt;/wbr&gt;function(pano) {&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'courier new', monospace;"&gt;          return {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;            location: {&lt;/div&gt;&lt;div&gt;              pano: pano,&lt;/div&gt;&lt;div&gt;              &lt;b&gt;description&lt;/b&gt;: "My panorama"&lt;/div&gt;&lt;div&gt;            },&lt;/div&gt;&lt;div&gt;            &lt;b&gt;links&lt;/b&gt;: links, // an array of StreetViewLink.&lt;/div&gt;&lt;div&gt;            &lt;b&gt;copyright&lt;/b&gt;: 'Imagery (c) 2009 Me',&lt;/div&gt;&lt;div&gt;            tiles: {&lt;/div&gt;&lt;div&gt;              tileSize: new google.maps.Size(512, 512),&lt;/div&gt;&lt;div&gt;              worldSize: new google.maps.Size(6000, 3000),&lt;/div&gt;&lt;div&gt;              &lt;b&gt;originHeading&lt;/b&gt;: 90, // To align the panorama with the headings in the links.&lt;/div&gt;&lt;div&gt;              getTileUrl: function(room, zoom, x, y) {&lt;/div&gt;&lt;div&gt;                return "http://mydomain/somepath/" + room + '_' + zoom + '_' + x + '_' + y + '.jpg';&lt;/div&gt;&lt;div&gt;              }&lt;/div&gt;&lt;div&gt;            }&lt;/div&gt;&lt;div&gt;          };&lt;/div&gt;&lt;div&gt;        });&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;        panorama.setPano('panorama'&lt;wbr&gt;&lt;/wbr&gt;);&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;The originHeading is the compass reading at the point where the left and right borders of the panorama join. &lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;For example, have a look at this tile set: &lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Zoom 0:&lt;/div&gt;&lt;div&gt;&lt;a href="http://syd-office-panos.appspot.com/p/reception_0_0_0.jpg"&gt;http://syd-office-panos.appspot.com/p/reception_0_0_0.jpg&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Zoom 1:&lt;/div&gt;&lt;div&gt;&lt;a href="http://syd-office-panos.appspot.com/p/reception_1_0_0.jpg"&gt;http://syd-office-panos.appspot.com/p/reception_1_0_0.jpg&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://syd-office-panos.appspot.com/p/reception_1_1_0.jpg"&gt;http://syd-office-panos.appspot.com/p/reception_1_1_0.jpg&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;To test this tileset, add this code on your page:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;pre&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;function initialize() {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;  var panorama = new google.maps.StreetViewPanorama(&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;    document.getElementById('streetview'),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;    {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;      panoProvider: function(pano) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;        return {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;          location: {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;            pano: pano,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;            description: 'Google Australia - Reception'&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;          },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;          copyright: 'Imagery \xA9 2010 Google Inc.',&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;          links: [],&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;          tiles: {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;            tileSize: new google.maps.Size(512, 512),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;            worldSize: new google.maps.Size(8192, 4096),&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;            originHeading: 0,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;            getTileUrl: function(room, zoom, x, y) {&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;              return 'http://syd-office-panos.appspot.com/p/reception_' +&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;                  zoom + '_' + x + '_' + y + '.jpg';&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;            }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;          }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;        };&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;      },&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;      pano: 'google'&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;  );&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-5622807421191618838?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/zYTFAc9X5qw" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/zYTFAc9X5qw/how-to-create-and-display-custom.html</link><author>noreply@blogger.com (Marc (Google Employee))</author><thr:total>13</thr:total><feedburner:origLink>http://blog.mridey.com/2010/05/how-to-create-and-display-custom.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-905688989501106986</guid><pubDate>Thu, 20 May 2010 02:17:00 +0000</pubDate><atom:updated>2010-05-27T11:02:46.665+10:00</atom:updated><title>Custom panoramas in Maps Javascript API v3 - Street View</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Y6UXlmdNCDf2HjsMSlC9QFe79XU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Y6UXlmdNCDf2HjsMSlC9QFe79XU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Y6UXlmdNCDf2HjsMSlC9QFe79XU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Y6UXlmdNCDf2HjsMSlC9QFe79XU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;How to display a custom panorama &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt; &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;Register a pano provider in the panorama that returns a StreetViewPanoramaData. The critical element is the 'tiles' property that defines the set of tiles required for the panorama.&lt;/p&gt;&lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;panorama.registerPanoProvider(function(pano) {&lt;br /&gt;return {&lt;br /&gt;location: {&lt;br /&gt;pano: pano,&lt;br /&gt;},&lt;br /&gt;tiles: {&lt;br /&gt;tileSize: new google.maps.Size(256, 256),&lt;br /&gt;worldSize: new google.maps.Size(256 * 64, 256 * 32),&lt;br /&gt;originHeading: 110,&lt;br /&gt;getTileUrl: function(pano, zoom, x, y) {&lt;br /&gt;return 'http://someurl/somepath/' + pano + '/' + zoom + '_' + x + '_' + y + '.png';&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;};&lt;br /&gt;});&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;How to set the address text in a custom panorama&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt; &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in; "&gt;&lt;span&gt;Set the description value of the StreetViewLocation in the &lt;/span&gt;StreetViewPanoramaData object return by the panoProvider.&lt;/p&gt;&lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;span&gt;panorama.registerPanoProvider(function(pano) {&lt;br /&gt;return {&lt;br /&gt;location: {&lt;br /&gt;...&lt;br /&gt;description: 'Address Text'&lt;br /&gt;},&lt;br /&gt;...&lt;br /&gt;};&lt;br /&gt;});&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;How to set the copyright in a custom panorama &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt; &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;span&gt;Set the copyright value in the &lt;/span&gt;StreetViewPanoramaData object return by the panoProvider.&lt;/p&gt;&lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;span&gt;panorama.registerPanoProvider(function(pano) {&lt;br /&gt;return {&lt;br /&gt;copyright: 'Copyright text',&lt;br /&gt;...&lt;br /&gt;};&lt;br /&gt;});&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;How to set the links in a custom panorama &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt; &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;span&gt;Provide a links array of StreetViewLink in the StreetViewPanoramaData object return by the panoProvider.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;span&gt;panorama.registerPanoProvider(function(pano) {&lt;br /&gt;return {&lt;br /&gt;links: [&lt;br /&gt;{&lt;br /&gt;'heading': 171,&lt;br /&gt;'description' : 'Link Text 1',&lt;br /&gt;'pano' : '5pXLKKqtDowwU0mrpx8pWw'&lt;br /&gt;},&lt;br /&gt;{&lt;br /&gt;'heading': 351,&lt;br /&gt;'description' : 'Link Text 2',&lt;br /&gt;'pano' : '0682ricVXBNcNuEcpSb-rA'&lt;br /&gt;}&lt;br /&gt;],&lt;br /&gt;...&lt;br /&gt;};&lt;br /&gt;});&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;How to set specify the color and opacity of a link in a custom panorama&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt; &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;span&gt;Set the roadColor and roadOpacity fields in the StreetViewLink objects in the links array.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;span&gt;panorama.registerPanoProvider(function(pano) {&lt;br /&gt;return {&lt;br /&gt;links: [&lt;br /&gt;{&lt;br /&gt;...&lt;br /&gt;'roadColor' : '#0020C0',&lt;br /&gt;'roadOpacity' : 0.6&lt;br /&gt;},&lt;br /&gt;...&lt;br /&gt;],&lt;br /&gt;...&lt;br /&gt;};&lt;br /&gt;});&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-905688989501106986?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/XnJTeKpM2yY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/XnJTeKpM2yY/custom-panoramas-in-maps-javascript-api.html</link><author>noreply@blogger.com (Marc (Google Employee))</author><thr:total>0</thr:total><feedburner:origLink>http://blog.mridey.com/2010/05/custom-panoramas-in-maps-javascript-api.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-1681414390626004796</guid><pubDate>Thu, 20 May 2010 02:13:00 +0000</pubDate><atom:updated>2011-09-27T16:20:26.348+10:00</atom:updated><title>Controls in Maps Javascript API v3 - Street View</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/d_UeqMP_0scagQCnSEZ3W1LAObo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/d_UeqMP_0scagQCnSEZ3W1LAObo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/d_UeqMP_0scagQCnSEZ3W1LAObo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/d_UeqMP_0scagQCnSEZ3W1LAObo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Controls in Street View are very similar to the Map controls.&lt;/p&gt;&lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt;How to show/hide the address control&lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt; &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.set('addressControl', true/false); &lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;or&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt; &lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.setOptions({&lt;br /&gt;addressControl: true/false&lt;br /&gt;});&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;&lt;br /&gt;&lt;/font&gt; &lt;/p&gt;&lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt;how to position the address control in the panorama &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt; &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.setOptions({&lt;br /&gt;'addressControlOptions': {&lt;br /&gt;'position': google.maps.ControlPosition.TOP_RIGHT,&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;});&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;&lt;br /&gt;&lt;/font&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt;How to show/hide the links control &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt; &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.set('linksControl', true/false); &lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;or&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt; &lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.setOptions({&lt;br /&gt;linksControl: true/false&lt;br /&gt;});&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;&lt;br /&gt;&lt;/font&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt;How to add a link in the links control &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt; &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;var links = panorama.getLinks();&lt;br /&gt;links.push({&lt;br /&gt;'yaw': 150,&lt;br /&gt;'description' : 'For Sale',&lt;br /&gt;'pano' : 'entrance',&lt;br /&gt;'roadColor': 'blue',&lt;br /&gt;'roadOpacity': 0.4&lt;br /&gt;});&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;then&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt; &lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.setLinks(links); &lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;or&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt; &lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.setOptions({&lt;br /&gt;links: links&lt;br /&gt;});&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;or&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt; &lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.notify('links'); &lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;&lt;br /&gt;&lt;/font&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt;how to add a custom control in the panorama &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt; &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;var aLink = document.createElement('a');&lt;br /&gt;aLink.innerHTML = "Hello";&lt;br /&gt;aLink.href = "http://google.com";&lt;br /&gt;panorama.controls[google.maps.ControlPosition.BOTTOM].push(aLink);&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;&lt;br /&gt;&lt;/font&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt;How to show/hide the close button &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt; &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.set('enableCloseButton', true/false); &lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;or&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt; &lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.setOptions({&lt;br /&gt;enableCloseButton: true/false&lt;br /&gt;});&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;&lt;br /&gt;&lt;/font&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt;How to detect the close button has been clicked &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt; &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;google.maps.event.addListener(panorama, 'closeclick', function() {}); &lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;&lt;br /&gt;&lt;/font&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt;How to show/hide the Navigation controls &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt; &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.set('navigationControl', true/false); &lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;or&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt; &lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.setOptions({&lt;br /&gt;navigationControl: true/false&lt;br /&gt;});&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;&lt;br /&gt;&lt;/font&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt;How to select the style and position of the navigation controls &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;&lt;font class="Apple-style-span"&gt; &lt;/font&gt;&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.set('navigationControlOptions', {&lt;br /&gt;position: google.maps.ControlPosition.TOP_LEFT,&lt;br /&gt;style: google.maps.NavigationControlStyle.ZOOM_PAN&lt;br /&gt;});&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;or&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt; &lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;panorama.setOptions({&lt;br /&gt;&lt;/font&gt;&lt;font class="Apple-style-span" style="font-family: verdana; "&gt;navigationControlOptions: {&lt;br /&gt;position: google.maps.ControlPosition.TOP_LEFT,&lt;br /&gt;style: google.maps.NavigationControlStyle.ZOOM_PAN&lt;br /&gt;}&lt;br /&gt;});&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;font class="Apple-style-span"&gt;&lt;br /&gt;&lt;/font&gt;&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-1681414390626004796?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/r49ihiDUihk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/r49ihiDUihk/controls-in-maps-javascript-api-v3.html</link><author>noreply@blogger.com (Marc (Google Employee))</author><thr:total>8</thr:total><feedburner:origLink>http://blog.mridey.com/2010/05/controls-in-maps-javascript-api-v3.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-3031353546147610665</guid><pubDate>Thu, 20 May 2010 02:02:00 +0000</pubDate><atom:updated>2010-05-27T09:59:32.141+10:00</atom:updated><title>Events, markers, infowindows and overlays in Maps Javascript API v3 - Street View</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4v2hoGS7j2hr4cKlEQ_sfl98xuQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4v2hoGS7j2hr4cKlEQ_sfl98xuQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4v2hoGS7j2hr4cKlEQ_sfl98xuQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4v2hoGS7j2hr4cKlEQ_sfl98xuQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;How to monitor changes to pano Id&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt; &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font face="Courier 10 Pitch"&gt;google.maps.event.addListener(panorama, 'pano_changed', function() {}); &lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;How to monitor changes to position &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt; &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font face="Courier 10 Pitch"&gt;google.maps.event.addListener(panorama, 'position_changed', function() {}); &lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;How to monitor changes to the point of view &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt; &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font face="Courier 10 Pitch"&gt;google.maps.event.addListener(panorama, 'pov_changed', function() {}); &lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;How to add a marker in the panorama&lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt; &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font face="Courier 10 Pitch"&gt;Markers by default are shared between the map and the panorama. If you create a separate panorama, you can add markers into it using:&lt;/font&gt;&lt;/p&gt;&lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font face="Courier 10 Pitch"&gt;var marker = new google.maps.Marker();&lt;br /&gt;marker.setMap(panorama);&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;How to add an infowindow in the panorama &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt; &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font face="Courier 10 Pitch"&gt;var infowindow = new google.maps.InfoWindow();&lt;br /&gt;infowindow.open(panorama);&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt;how to add a custom overlay in the panorama &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;u&gt; &lt;/u&gt;&lt;/p&gt; &lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font face="Courier 10 Pitch"&gt;To add a custom overlay on a panorama, follow the same logic as a custom overlay in the map. Derive from OverlayView, implement draw, onAdd, onRemove ... and add it to the panorama using setMap(panorama):&lt;/font&gt;&lt;/p&gt;&lt;p style="margin-left: 0.49in; margin-bottom: 0in"&gt;&lt;font face="Courier 10 Pitch"&gt;function CustomOverlay() {};&lt;br /&gt;CustomOverlay.prototype = new google.maps.OverlayView;&lt;br /&gt;var customOverlay = new CustomOverlay();&lt;br /&gt;customOverlay.setMap(panorama);&lt;/font&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in"&gt;&lt;br /&gt;&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-3031353546147610665?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/p7gUk9J2N_Q" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/p7gUk9J2N_Q/events-markers-infowindows-and-overlays.html</link><author>noreply@blogger.com (Marc (Google Employee))</author><thr:total>4</thr:total><feedburner:origLink>http://blog.mridey.com/2010/05/events-markers-infowindows-and-overlays.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-4435866355922438600</guid><pubDate>Thu, 20 May 2010 01:48:00 +0000</pubDate><atom:updated>2010-05-20T14:35:53.358+10:00</atom:updated><title>Enabling and initializing Street View in Maps Javascript API v3</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/ElDIg0xxmdpSZCaommLdA5wJbL4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ElDIg0xxmdpSZCaommLdA5wJbL4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/ElDIg0xxmdpSZCaommLdA5wJbL4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/ElDIg0xxmdpSZCaommLdA5wJbL4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="padding:20px"&gt;&lt;h3 style="color: rgb(85, 85, 85); font-family: sans-serif; margin-left: 10px; font-size: medium; "&gt;How to enable Street View&lt;/h3&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;map&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;set&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;(&lt;/span&gt;&lt;span class="str" style="color: rgb(0, 136, 0); "&gt;'streetViewControl'&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;,&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; &lt;/span&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;true&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;or&lt;/p&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;map&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;setOptions&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;({&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;streetViewControl&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;:&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; &lt;/span&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;true&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;});&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;h3 style="color: rgb(85, 85, 85); font-family: sans-serif; margin-left: 10px; font-size: medium; "&gt;&lt;a name="How_to_access_the_panorama_in_th"&gt;&lt;/a&gt;How to access the panorama in the map&lt;/h3&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;var&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; panorama &lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;=&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; map&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;getStreetView&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;();&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;h3 style="color: rgb(85, 85, 85); font-family: sans-serif; margin-left: 10px; font-size: medium; "&gt;&lt;a name="How_to_know_if_the_panorama_is_d"&gt;&lt;/a&gt;How to know if the panorama is displayed&lt;/h3&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;var&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; panoramaDisplayed &lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;=&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; panorama&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;getVisible&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;();&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;h3 style="color: rgb(85, 85, 85); font-family: sans-serif; margin-left: 10px; font-size: medium; "&gt;&lt;a name="How_to_set_a_manual_Pano_Id"&gt;&lt;/a&gt;How to set a manual Pano Id&lt;/h3&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;panorama&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;setPano&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;(&lt;/span&gt;&lt;span class="str" style="color: rgb(0, 136, 0); "&gt;'-gfXi6db7jFB-cwAkTbBgA'&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;or&lt;/p&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;panorama&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;setOptions&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;({&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;pano&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;:&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; &lt;/span&gt;&lt;span class="str" style="color: rgb(0, 136, 0); "&gt;'-gfXi6db7jFB-cwAkTbBgA'&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;});&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;h3 style="color: rgb(85, 85, 85); font-family: sans-serif; margin-left: 10px; font-size: medium; "&gt;&lt;a name="How_to_set_a_manual_position"&gt;&lt;/a&gt;How to set a manual position&lt;/h3&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;panorama&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;setPosition&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;(&lt;/span&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;new&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; google&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;maps&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="typ" style="color: rgb(102, 0, 102); "&gt;LatLng&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;(&lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;48&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;85969&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;,&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; &lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;2&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;29720&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;));&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;or&lt;/p&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;panorama&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;setOptions&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;({&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;position&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;:&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; &lt;/span&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;new&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; google&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;maps&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="typ" style="color: rgb(102, 0, 102); "&gt;LatLng&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;(&lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;48&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;85969&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;,&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; &lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;2&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;29720&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;)&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;});&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;h3 style="color: rgb(85, 85, 85); font-family: sans-serif; margin-left: 10px; font-size: medium; "&gt;&lt;a name="How_to_set_the_point_of_view"&gt;&lt;/a&gt;How to set the point of view&lt;/h3&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;panorama&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;setPov&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;({&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;heading&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;:&lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;30&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;,&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; pitch&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;:&lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;0&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;,&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; zoom&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;:&lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;4&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;});&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;or&lt;/p&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;panorama&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;setOptions&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;({&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;pov&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;:&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; &lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;{&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;heading&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;:&lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;30&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;,&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; pitch&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;:&lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;0&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;,&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; zoom&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;:&lt;/span&gt;&lt;span class="lit" style="color: rgb(0, 102, 102); "&gt;4&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;}&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;});&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;h3 style="color: rgb(85, 85, 85); font-family: sans-serif; margin-left: 10px; font-size: medium; "&gt;&lt;a name="How_to_create_a_panorama_without"&gt;&lt;/a&gt;How to create a panorama without a map&lt;/h3&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;var&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; div &lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;=&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; document&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;getElementById&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;(&lt;/span&gt;&lt;span class="str" style="color: rgb(0, 136, 0); "&gt;'panoramadiv'&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;);&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;var&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; panorama &lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;=&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; &lt;/span&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;new&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; google&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;maps&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="typ" style="color: rgb(102, 0, 102); "&gt;StreetViewPanorama&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;(&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;div&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;h3 style="color: rgb(85, 85, 85); font-family: sans-serif; margin-left: 10px; font-size: medium; "&gt;&lt;a name="How_to_have_a_separate_panorama_"&gt;&lt;/a&gt;How to have a separate panorama next to the map&lt;/h3&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;var&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; div &lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;=&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; document&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;getElementById&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;(&lt;/span&gt;&lt;span class="str" style="color: rgb(0, 136, 0); "&gt;'panoramadiv'&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;);&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;var&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; panorama &lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;=&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; &lt;/span&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;new&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; google&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;maps&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="typ" style="color: rgb(102, 0, 102); "&gt;StreetViewPanorama&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;(&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;div&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;);&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;map&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;setStreetView&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;(&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;panorama&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;or&lt;/p&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;pre class="prettyprint" style="color: rgb(0, 96, 0); background-color: rgb(224, 234, 244); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(136, 136, 136); border-right-color: rgb(136, 136, 136); border-bottom-color: rgb(136, 136, 136); border-left-color: rgb(136, 136, 136); padding-left: 2px; padding-top: 2px; padding-bottom: 2px; overflow-x: auto; overflow-y: auto; padding-right: 2px; "&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;var&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; div &lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;=&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; document&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;getElementById&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;(&lt;/span&gt;&lt;span class="str" style="color: rgb(0, 136, 0); "&gt;'panoramadiv'&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;);&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;var&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; panorama &lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;=&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; &lt;/span&gt;&lt;span class="kwd" style="color: rgb(0, 0, 136); "&gt;new&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; google&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;maps&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="typ" style="color: rgb(102, 0, 102); "&gt;StreetViewPanorama&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;(&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;div&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;);&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;map&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;.&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;setOptions&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;({&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt;&lt;br /&gt;streetView&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;:&lt;/span&gt;&lt;span class="pln" style="color: rgb(0, 0, 0); "&gt; panorama&lt;br /&gt;&lt;/span&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;});&lt;/span&gt;&lt;/pre&gt;&lt;div&gt;&lt;span class="pun" style="color: rgb(102, 102, 0); "&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;p style="font-family: 'Times New Roman'; font-size: medium; "&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-4435866355922438600?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/CcGDiVGO1-Q" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/CcGDiVGO1-Q/enabling-and-initializing-street-view.html</link><author>noreply@blogger.com (Marc Ridey)</author><thr:total>15</thr:total><feedburner:origLink>http://blog.mridey.com/2010/05/enabling-and-initializing-street-view.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-7467011517449443163</guid><pubDate>Thu, 25 Mar 2010 12:00:00 +0000</pubDate><atom:updated>2010-03-25T23:38:02.991+11:00</atom:updated><title>Using MarkerImage in Maps Javascript API v3</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HOdmgOEaS-6JnMmYSkXl_Tv25mo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HOdmgOEaS-6JnMmYSkXl_Tv25mo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HOdmgOEaS-6JnMmYSkXl_Tv25mo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HOdmgOEaS-6JnMmYSkXl_Tv25mo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;When creating custom markers, you need to supply two images, the icon and the shadow. While you can supply a simple URL for each property, using MarkerImage allows you more flexibility and improves performance.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-size:large;"&gt;1. Creating a simple image:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The simplest marker is one made of individual icon and shadow images, with the anchor point (The point used to position the marker) located in the middle of the bottom edge of the image, like the standard marker using by the API.&lt;br /&gt;In this situation, you only need to speficy the image URL such as:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var icon = new google.maps.MarkerImage("http://domain/path/image.png");&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;2. Specifying an anchor point&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Depending of the shape of the marker, you may not want the middle of the bottom edge to be used as the anchor point. For example, in this &lt;a href="http://code.google.com/apis/maps/documentation/v3/examples/icon-simple.html"&gt;sample&lt;/a&gt;, the anchor point of the beach flag is at the bottom left corner.&lt;br /&gt;In those situation, you need to specify the anchor point of the image as the fourth parameter. This is a value of type Point, relative to the top left corner of the image with positive X going right and positive Y going down.&lt;br /&gt;For example, if the image "beach_flag.png" is 20*32 pixels, we would use:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var icon = new google.maps.MarkerImage("http://domain/path/beach_flag.png", null, null, new google.maps.Point(0, 32));&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;3. Resizing the image&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;If you need to display the image larger or smaller than its original size, supply the scaledImage parameter:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var icon = new google.maps.MarkerImage("http://domain/path/image.png", null, null, null, new google.maps.Size(64, 64));&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Note that if you use both size and anchor, the anchor value needs to be specified after scaling.&lt;br /&gt;Combining the two previous examples, we would have:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var icon = new google.maps.MarkerImage("http://domain/path/beach_flag.png", null, null, new google.maps.Point(0, 64), new google.maps.Size(40, 64));&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Note the change to the anchor from 0, 32 to 0, 64.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;4. Using a sprite image&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;One simple way to imrove the performance of your website is to use sprite images. It means using a single image that contains many of the images you need of the site then using a section of it as required. The browser only makes a single call to download the image where before it would have made many.&lt;br /&gt;To create a MarkerImage from a sprite image, you need to specify the origin and size of the section of the image you want to use to create the icon.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var icon = new google.maps.MarkerImage("http://domain/path/sprite.png", new google.maps.Size(12, 20), new google.maps.Point(100, 34));&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;You can, if you need, also provide the anchor point. The valoue of the anchor is relative to the section of the image, not the whole image.&lt;br /&gt;For example, to use the center of the sprite image above as the anchor point, we would have:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var icon = new google.maps.MarkerImage("http://domain/path/sprite.png", new google.maps.Size(12, 20), new google.maps.Point(100, 34), new google.maps.Point(6, 10));&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;5. Using a scaled sprite image&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;To combine spriting and scaling, you need to supply a scaled section size as well as the scaled image size.&lt;br /&gt;For example, if we want to display the section in the previous example of size 12*20 pixels, but display it 24*40 pixels, from an image originally 200*300 in size we would have:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var icon = new google.maps.MarkerImage("http://domain/path/sprite.png", new google.maps.Size(24, 40), new google.maps.Point(200, 68), new google.maps.Point(12, 20), new google.maps.Size(400, 600));&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;To display a scaled image or a scaled prite image, just supply the size, origin, anchor and scaledSize parameters with the scale factor applied.&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;6. Improving performance&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;They are two ways to improve the performance of MarkerImage:&lt;br /&gt;&lt;br /&gt;- When you know the size of the image, specify it. If the size is not supplied, we make a call to download the image and read its size. While most browsers will cache the image and not download it again, this is not true in all cases and it may trigger the download of the image earlier than required, delaying the display of the map.&lt;br /&gt;- When displaying multiple markers with the same shadow or icon, reuse the MarkerImage for all the markers:&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var icon = new google.maps.MarkerImage(...);&lt;br /&gt;for (...) {&lt;br /&gt;  var marker = new google.maps.Marker({&lt;br /&gt;    icon: icon,&lt;br /&gt;    ...&lt;br /&gt;  };&lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-7467011517449443163?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/6rdit7qe-dY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/6rdit7qe-dY/using-markerimage-in-maps-javascript.html</link><author>noreply@blogger.com (Marc Ridey)</author><thr:total>19</thr:total><feedburner:origLink>http://blog.mridey.com/2010/03/using-markerimage-in-maps-javascript.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-1010489928733011015</guid><pubDate>Wed, 24 Mar 2010 10:21:00 +0000</pubDate><atom:updated>2010-03-24T22:14:28.767+11:00</atom:updated><title>Maps Javascript API v3 - More about the MVCObject class</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QHkSs2FsKAw0uzdgFbHdFvzX1MQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QHkSs2FsKAw0uzdgFbHdFvzX1MQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QHkSs2FsKAw0uzdgFbHdFvzX1MQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QHkSs2FsKAw0uzdgFbHdFvzX1MQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;If you’re doing development using the new Google Maps JavaScript API v3, you will have noticed that all the core classes are derived from the MVCObject class.&lt;br /&gt;Knowing when and how to use the features built into the MVCObject class will make your Maps API v3 development easier.&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;1.     Accessors&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;&lt;br /&gt;To store and retrieve values from an MVCObject, do not access the properties directly, instead use the provided accessor methods.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;get(key): Retrieves a value from the MVCObject.&lt;br /&gt;set(key, value): Stores a value in the MVCObject.&lt;br /&gt;setValues(keyValuePairs): Sets multiple values in the MVCObject.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;For example:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var a = new google.maps.MVCObject();&lt;br /&gt;a.set(‘level’, 2);&lt;br /&gt;alert(a.get(‘level’));   // Returns 2&lt;br /&gt;var b = new google.maps.MVCObject();&lt;br /&gt;b.setValues({&lt;br /&gt;&amp;nbsp;&amp;nbsp;level: 2,&lt;br /&gt;&amp;nbsp;&amp;nbsp;index: 3,&lt;br /&gt;&amp;nbsp;&amp;nbsp;description: ‘Hello world.’&lt;br /&gt;});&lt;br /&gt;alert(b.get(‘index’));   // Returns 3&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;2.     Binding&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Binding two properties between two MVCObjects allows changes to one object to be replicated in the object other.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;bindTo(targetKey, source, sourceKey): Binds the sourceKey property of the source to the targetKey property of the MVCObject. Effectively, it means that calling get(targetKey) on the MVCObject calls source.get(sourceKey).&lt;br /&gt;&lt;br /&gt;Unbind(targetKey): Removes the binding between the MVCObject and the source but retains the value of the property, so calling get(targetKey) on the MVCObject before or after unbinding returns the same value. This is not true once the sourceKey property of the source is changed.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;For example:&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var a = new google.maps.MVCObject();&lt;br /&gt;a.set(‘level’, 2);&lt;br /&gt;&lt;br /&gt;var b = new google.maps.MVCObject();&lt;br /&gt;b.bindTo(‘index’, a, ‘level’);&lt;br /&gt;alert(b.get(‘index’));   // Returns 2.&lt;br /&gt;&lt;br /&gt;// Changes to the source are visible on the target&lt;br /&gt;a.set(‘level’, 3);&lt;br /&gt;alert(b.get(‘index’));   // Returns 3.&lt;br /&gt;&lt;br /&gt;// Changes to the target are visible on the source&lt;br /&gt;b.set(‘index’, 4);&lt;br /&gt;alert(a.get(‘level’));   // Returns 4.&lt;br /&gt;&lt;br /&gt;// There can be multiple values bounds to the same source&lt;br /&gt;var c = new google.maps.MVCObject();&lt;br /&gt;c.bindTo(‘zoom’, a, ‘level’);&lt;br /&gt;alert(c.get(‘zoom’));   // Returns 4.&lt;br /&gt;&lt;br /&gt;// Unbound properties are not changed when the source is changed&lt;br /&gt;b.unbind(‘index’);&lt;br /&gt;alert(b.get(‘index’));   // Returns 4. The value hasn’t changed when unbound.&lt;br /&gt;c.set(‘zoom’, 5);&lt;br /&gt;alert(a.get(‘level’));   // Returns 5, c.zoom is bound to a.level.&lt;br /&gt;alert(b.get(‘index’));   // Returns 4, b.index is not bound to anything.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Note that when bound, the two values are not duplicated but rather the getter of the bound property calls the getter of the source property.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;In this code:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var map = new google.maps.Map(div, {…});&lt;br /&gt;var marker = new google.maps.Marker({…});&lt;br /&gt;marker.bindTo(‘position’, map, ‘center’);&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;The marker LatLng position is bound to the map’s center. This causes the maker position to be updated to the center of the map, everytime the map’s center changes. Effectively, it keeps the marker at the center of the map.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;3.     Events&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Binding ensures that values are kept in sync, but you need to be notified that the values have changed to be able to act on it. The MVCObject provides two notification mechanisms: the changed method and changed events.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;The changed method is a generic handler for state changes. Override this in derived classes to handle arbitrary state changes.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;For example (See &lt;a href="http://blog.mridey.com/2009/09/label-overlay-example-for-google-maps.html"&gt;http://blog.mridey.com/2009/09/label-overlay-example-for-google-maps.html&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;function Label() {};&lt;br /&gt;Label.prototype = new google.maps.OverlayView;   // OverlayView derives from MVCObject.&lt;br /&gt;&lt;br /&gt;Label.prototype.changed = function(key) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (key == ‘position’ || key == ‘text’) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.draw();&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;};&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;Label.changed is called from changes to its properties with the parameter ‘key’ set to the name of the property that was set.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;The second method available to monitor changes to MVC properties is the ‘changed’ event. Every time a property is set, an event named ‘xxx_changed’ (where ‘xxx’ is the lowercase value of the key) is triggered. You can listen to these events using google.maps.event.addListener.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;For example:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;&lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;var a = new google.maps.MVCObject();&lt;br /&gt;google.maps.event.addListener(a, ‘level_changed’, function() {&lt;br /&gt;  alert(‘a.level has changed and the new value is ‘ + a.get(‘level’));&lt;br /&gt;});&lt;br /&gt;a.set(‘level’, 2); // Will display the alert message.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;The changed events follow bound properties. If a.X is bound to b.X and b.X is bound to c.X, setting either a.X, b.X or C.X will cause the 'x_changed' event to be triggered on a, b, and c. The order in which the events are triggered depends o the order in which the values where bound and the listeners were attached.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;Note that the changed events are triggered synchronously within the call to set(). In the example above, the alert dialog is displayed before the a.set() calls returns.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-1010489928733011015?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/2QdH_q7XCfw" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/2QdH_q7XCfw/maps-javascript-api-v3-more-about.html</link><author>noreply@blogger.com (Marc Ridey)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.mridey.com/2010/03/maps-javascript-api-v3-more-about.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-7934561568072561320</guid><pubDate>Wed, 30 Sep 2009 04:12:00 +0000</pubDate><atom:updated>2009-09-30T14:24:08.344+10:00</atom:updated><title>Listening to map events in Google Maps API v3 OverlayView</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nuIgzpY0ETWaGY1QwNWYP-loqzA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nuIgzpY0ETWaGY1QwNWYP-loqzA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nuIgzpY0ETWaGY1QwNWYP-loqzA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nuIgzpY0ETWaGY1QwNWYP-loqzA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;In my previous post, I showed how to create a simple Label overlay. In that example, the draw method was only called when the position of the overlay relative to the map needed to be recalculated or when the text for the label had changed.&lt;br /&gt;&lt;br /&gt;But what if the look/content of the overlay you want to create depends on the map center or the map bounds. Currently, OverlayView.draw is not called if the map is dragged for example.&lt;br /&gt;&lt;br /&gt;I've created below a 'Center' overlay to demonstrate how to listen to map events in the overlay. &lt;br /&gt;&lt;br /&gt;first, in center.js I have:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// Define the overlay, derived from google.maps.OverlayView&lt;br /&gt;function Center(opt_options) {&lt;br /&gt;  // Initialization&lt;br /&gt;  this.setValues(opt_options);&lt;br /&gt;&lt;br /&gt;  // Center specific&lt;br /&gt;  var div1 = document.createElement('div');&lt;br /&gt;  div1.style.cssText = 'position: absolute; left: -20px; top: -20px; ' +&lt;br /&gt;                       'border-right: 1px solid blue; border-bottom: 1px solid blue; width: 19px; height: 19px';&lt;br /&gt;  var div2 = document.createElement('div');&lt;br /&gt;  div2.style.cssText = 'position: absolute; left: 1px; top: -20px; ' +&lt;br /&gt;                       'border-left: 1px solid blue; border-bottom: 1px solid blue; width: 19px; height: 19px';&lt;br /&gt;  var div3 = document.createElement('div');&lt;br /&gt;  div3.style.cssText = 'position: absolute; left: -20px; top: 1px; ' +&lt;br /&gt;                       'border-right: 1px solid blue; border-top: 1px solid blue; width: 19px; height: 19px';&lt;br /&gt;  var div4 = document.createElement('div');&lt;br /&gt;  div4.style.cssText = 'position: absolute; left: 1px; top: 1px; ' +&lt;br /&gt;                       'border-left: 1px solid blue; border-top: 1px solid blue; width: 19px; height: 19px';&lt;br /&gt;&lt;br /&gt;  var div = this.div_ = document.createElement('div');&lt;br /&gt;  div.appendChild(div1);&lt;br /&gt;  div.appendChild(div2);&lt;br /&gt;  div.appendChild(div3);&lt;br /&gt;  div.appendChild(div4);&lt;br /&gt;  div.style.cssText = 'position: absolute; display: none';&lt;br /&gt;};&lt;br /&gt;Center.prototype = new google.maps.OverlayView;&lt;br /&gt;&lt;br /&gt;// Implement onAdd&lt;br /&gt;Center.prototype.onAdd = function() {&lt;br /&gt;  var pane = this.getPanes().overlayLayer;&lt;br /&gt;  pane.appendChild(this.div_);&lt;br /&gt;&lt;br /&gt;  // Ensures the center is redrawn if the map center changes&lt;br /&gt;  var me = this;&lt;br /&gt;  this.listeners_ = [&lt;br /&gt;    google.maps.event.addListener(this.getMap(), 'center_changed',&lt;br /&gt;        function() { me.draw(); }),&lt;br /&gt;  ];&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// Implement onRemove&lt;br /&gt;Center.prototype.onRemove = function() {&lt;br /&gt;  this.div_.parentNode.removeChild(this.div_);&lt;br /&gt;&lt;br /&gt;  // Label is removed from the map, stop updating its position/text.&lt;br /&gt;  for (var i = 0, I = this.listeners_.length; i &amp;lt; I; ++i) {&lt;br /&gt;    maps.google.event.removeListener(this.listeners_[i]);&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// Implement draw&lt;br /&gt;Center.prototype.draw = function() {&lt;br /&gt;  var projection = this.getProjection();&lt;br /&gt;  var position = projection.fromLatLngToDivPixel(this.getMap().getCenter());&lt;br /&gt;&lt;br /&gt;  var div = this.div_;&lt;br /&gt;  div.style.left = position.x + 'px';&lt;br /&gt;  div.style.top = position.y + 'px';&lt;br /&gt;  div.style.display = 'block';&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and in the map initialization I just added:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  &amp;lt;script type="text/javascript" src="center.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;and&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  var center = new Center({&lt;br /&gt;    map: map&lt;br /&gt;  });&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Adding the Center object to the map creates a cross at the center of the map. When the map is dragged or zoomed, the overlay is redrawn, allowing it to stay centered.&lt;br /&gt;&lt;br /&gt;The result looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-d8IC9KSirE/SsLb2wfJg-I/AAAAAAAAGD4/z4hqN_c3vlA/s1600-h/CenterOverlay.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 298px; height: 400px;" src="http://1.bp.blogspot.com/_-d8IC9KSirE/SsLb2wfJg-I/AAAAAAAAGD4/z4hqN_c3vlA/s400/CenterOverlay.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5387109838063502306" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-7934561568072561320?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/dHr1VDiaApE" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/dHr1VDiaApE/in-my-previous-post-i-showed-how-to.html</link><author>noreply@blogger.com (Marc Ridey)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_-d8IC9KSirE/SsLb2wfJg-I/AAAAAAAAGD4/z4hqN_c3vlA/s72-c/CenterOverlay.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://blog.mridey.com/2009/09/in-my-previous-post-i-showed-how-to.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-1306389769807676066</guid><pubDate>Tue, 29 Sep 2009 06:30:00 +0000</pubDate><atom:updated>2010-02-25T09:09:17.994+11:00</atom:updated><title>Label overlay example for Google Maps API v3</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kMqjJ2_oEDiA3apDCOMaoodlZGA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kMqjJ2_oEDiA3apDCOMaoodlZGA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kMqjJ2_oEDiA3apDCOMaoodlZGA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kMqjJ2_oEDiA3apDCOMaoodlZGA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;Here's a simple example of creating a custom overlay class for Google Maps API v3. This Label overlay can either be used on its own, or bound to a marker.&lt;br /&gt;&lt;br /&gt;First, create the Label class and place it in a label.js file.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;// Define the overlay, derived from google.maps.OverlayView&lt;br /&gt;function Label(opt_options) {&lt;br /&gt; // Initialization&lt;br /&gt; this.setValues(opt_options);&lt;br /&gt;&lt;br /&gt; // Label specific&lt;br /&gt; var span = this.span_ = document.createElement('span');&lt;br /&gt; span.style.cssText = 'position: relative; left: -50%; top: -8px; ' +&lt;br /&gt;                      'white-space: nowrap; border: 1px solid blue; ' +&lt;br /&gt;                      'padding: 2px; background-color: white';&lt;br /&gt;&lt;br /&gt; var div = this.div_ = document.createElement('div');&lt;br /&gt; div.appendChild(span);&lt;br /&gt; div.style.cssText = 'position: absolute; display: none';&lt;br /&gt;};&lt;br /&gt;Label.prototype = new google.maps.OverlayView;&lt;br /&gt;&lt;br /&gt;// Implement onAdd&lt;br /&gt;Label.prototype.onAdd = function() {&lt;br /&gt; var pane = this.getPanes().overlayLayer;&lt;br /&gt; pane.appendChild(this.div_);&lt;br /&gt;&lt;br /&gt; // Ensures the label is redrawn if the text or position is changed.&lt;br /&gt; var me = this;&lt;br /&gt; this.listeners_ = [&lt;br /&gt;   google.maps.event.addListener(this, 'position_changed',&lt;br /&gt;       function() { me.draw(); }),&lt;br /&gt;   google.maps.event.addListener(this, 'text_changed',&lt;br /&gt;       function() { me.draw(); })&lt;br /&gt; ];&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// Implement onRemove&lt;br /&gt;Label.prototype.onRemove = function() {&lt;br /&gt; this.div_.parentNode.removeChild(this.div_);&lt;br /&gt;&lt;br /&gt; // Label is removed from the map, stop updating its position/text.&lt;br /&gt; for (var i = 0, I = this.listeners_.length; i &amp;lt; I; ++i) {&lt;br /&gt;   google.maps.event.removeListener(this.listeners_[i]);&lt;br /&gt; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// Implement draw&lt;br /&gt;Label.prototype.draw = function() {&lt;br /&gt; var projection = this.getProjection();&lt;br /&gt; var position = projection.fromLatLngToDivPixel(this.get('position'));&lt;br /&gt;&lt;br /&gt; var div = this.div_;&lt;br /&gt; div.style.left = position.x + 'px';&lt;br /&gt; div.style.top = position.y + 'px';&lt;br /&gt; div.style.display = 'block';&lt;br /&gt;&lt;br /&gt; this.span_.innerHTML = this.get('text').toString();&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then use label.js in the map initialization:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt; &amp;lt;meta http-equiv="content-type" content="text/html; charset=UTF-8"/&amp;gt;&lt;br /&gt; &amp;lt;title&amp;gt;Label Overlay Example&amp;lt;/title&amp;gt;&lt;br /&gt; &amp;lt;script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt; &amp;lt;script type="text/javascript" src="label.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt; &amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;   function initialize() {&lt;br /&gt;     var latLng = new google.maps.LatLng(40, -100);&lt;br /&gt;&lt;br /&gt;     var map = new google.maps.Map(document.getElementById('map_canvas'), {&lt;br /&gt;       zoom: 5,&lt;br /&gt;       center: latLng,&lt;br /&gt;       mapTypeId: google.maps.MapTypeId.ROADMAP&lt;br /&gt;     });&lt;br /&gt;&lt;br /&gt;     var marker = new google.maps.Marker({&lt;br /&gt;       position: latLng,&lt;br /&gt;       draggable: true,&lt;br /&gt;       map: map&lt;br /&gt;     });&lt;br /&gt;&lt;br /&gt;     var label = new Label({&lt;br /&gt;       map: map&lt;br /&gt;     });&lt;br /&gt;     label.bindTo('position', marker, 'position');&lt;br /&gt;     label.bindTo('text', marker, 'position');&lt;br /&gt;   };&lt;br /&gt; &amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body onload="initialize()"&amp;gt;&lt;br /&gt; &amp;lt;div id="map_canvas" style="height: 100%; width: 100%"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;When run, it looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-d8IC9KSirE/SsGungdzIlI/AAAAAAAAGDw/Cbuw4Oikck8/s1600-h/LabelOverlay.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 267px; height: 320px;" src="http://1.bp.blogspot.com/_-d8IC9KSirE/SsGungdzIlI/AAAAAAAAGDw/Cbuw4Oikck8/s320/LabelOverlay.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5386778623064875602" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Drag the marker around and the text of the label with update with the LatLng of the marker.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-1306389769807676066?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/LSRIs43SM04" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/LSRIs43SM04/label-overlay-example-for-google-maps.html</link><author>noreply@blogger.com (Marc Ridey)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_-d8IC9KSirE/SsGungdzIlI/AAAAAAAAGDw/Cbuw4Oikck8/s72-c/LabelOverlay.png" height="72" width="72" /><thr:total>97</thr:total><feedburner:origLink>http://blog.mridey.com/2009/09/label-overlay-example-for-google-maps.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-6470189921014648417</guid><pubDate>Fri, 11 Sep 2009 03:50:00 +0000</pubDate><atom:updated>2009-09-11T14:04:59.043+10:00</atom:updated><title>Hosting Google Maps in a Microsoft WPF application using XAML</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/hKl1VVQDL7oNaecLNQ6nNFA43DU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hKl1VVQDL7oNaecLNQ6nNFA43DU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/hKl1VVQDL7oNaecLNQ6nNFA43DU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hKl1VVQDL7oNaecLNQ6nNFA43DU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;Ever wondered how to implement Google Maps in a WPF application using XAML?&lt;br&gt;&lt;br /&gt;Find out how: &lt;a href="http://code.google.com/apis/maps/articles/flashmapinwpf.html"&gt;http://code.google.com/apis/maps/articles/flashmapinwpf.html&lt;/a&gt;&lt;br&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://gmaps-samples-flash.googlecode.com/svn/trunk/articles/wpf/image001.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 600px; height: 437px;" src="http://gmaps-samples-flash.googlecode.com/svn/trunk/articles/wpf/image001.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-6470189921014648417?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/uvIwBvJACTs" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/uvIwBvJACTs/hosting-google-maps-in-microsoft-wpf.html</link><author>noreply@blogger.com (Marc Ridey)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.mridey.com/2009/09/hosting-google-maps-in-microsoft-wpf.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-5742281859889603640</guid><pubDate>Mon, 04 May 2009 12:19:00 +0000</pubDate><atom:updated>2010-03-03T23:49:38.940+11:00</atom:updated><title>Filtered ObservableCollection</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/6A_m_OQxUeRLND6UjduD7R1NeEU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6A_m_OQxUeRLND6UjduD7R1NeEU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/6A_m_OQxUeRLND6UjduD7R1NeEU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/6A_m_OQxUeRLND6UjduD7R1NeEU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;span xmlns=''&gt;&lt;p&gt;On the project I'm working on at the moment, I have a class that stores items in an ObservableCollection. I needed to be able to expose in the same class different subsets of this collection, keeping them all in sync while allowing to add/remove/update elements in all the collections. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;For example, imagine you would like to create a collection of people ObservableCollection&amp;lt;People&amp;gt; but also have collection for Males and Females and pass these collections as parameters to other methods that can manipulate these collections (Add/Remove/Update People in the Males collection) and see the original collection updated.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;My first approach was to create an ObservableCollection for each subset and use the CollectionChanged event to maintain all the lists in sync. While it worked, it was very code heavy. So today I wrote a simple FilteredObservableCollection class. It encapsulates an ObservableCollection but only enumerates the items that comply with the filter. It's similar to the CollectionView but it still allows to Add/Remove/Update elements in the collection.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The class is not derived from an ObservableCollection since it needs to be able to attach to an existing collection but it expose all the interfaces and members for the observable collection:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;FilteredObservableCollection&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style='color:#2b91af'&gt;IList&lt;/span&gt;&amp;lt;T&amp;gt;, &lt;span style='color:#2b91af'&gt;ICollection&lt;/span&gt;&amp;lt;T&amp;gt;, &lt;span style='color:#2b91af'&gt;IEnumerable&lt;/span&gt;&amp;lt;T&amp;gt;, &lt;span style='color:#2b91af'&gt;IList&lt;/span&gt;, &lt;span style='color:#2b91af'&gt;ICollection&lt;/span&gt;, &lt;span style='color:#2b91af'&gt;IEnumerable&lt;/span&gt;, &lt;span style='color:#2b91af'&gt;INotifyCollectionChanged&lt;/span&gt;, &lt;span style='color:#2b91af'&gt;INotifyPropertyChanged&lt;br/&gt;&lt;/span&gt;{&lt;br/&gt;    &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;ObservableCollection&lt;/span&gt;&amp;lt;T&amp;gt; _collection;&lt;br/&gt;    &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;Predicate&lt;/span&gt;&amp;lt;T&amp;gt; _filter;&lt;br/&gt;    &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;event&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;NotifyCollectionChangedEventHandler&lt;/span&gt; _collectionchanged;&lt;br/&gt;    &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;event&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;PropertyChangedEventHandler&lt;/span&gt; _propertychanged;&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt; FilteredObservableCollection(&lt;span style='color:#2b91af'&gt;ObservableCollection&lt;/span&gt;&amp;lt;T&amp;gt; collection)&lt;br/&gt;    {&lt;br/&gt;        _filter = &lt;span style='color:blue'&gt;null&lt;/span&gt;;&lt;br/&gt;        _collection = collection;&lt;br/&gt;        _collection.CollectionChanged += &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;NotifyCollectionChangedEventHandler&lt;/span&gt;(OnCollectionChanged);&lt;br/&gt;        ((&lt;span style='color:#2b91af'&gt;INotifyPropertyChanged&lt;/span&gt;)_collection).PropertyChanged += &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;PropertyChangedEventHandler&lt;/span&gt;(OnPropertyChanged);&lt;br/&gt;    }&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;The two interesting bit in the Filtered collection are the handling on the CollectionChanged event and the enumerator:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The CollectionChanged event received from the encapsulated collection may not necessarily need to be passed by the filtered collection. An item added to or deleted from the main collection, if filtered out, should not generate an event for the filtered collection while a Change to an existing item may cause the item to appear in the list (it now complies with the filter) or disappear from the list (it no longer complies with the filter). &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;    &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;void&lt;/span&gt; OnCollectionChanged(&lt;span style='color:blue'&gt;object&lt;/span&gt; sender, &lt;span style='color:#2b91af'&gt;NotifyCollectionChangedEventArgs&lt;/span&gt; e)&lt;br/&gt;    {&lt;br/&gt;        &lt;span style='color:blue'&gt;if&lt;/span&gt; (_collectionchanged != &lt;span style='color:blue'&gt;null&lt;/span&gt;)&lt;br/&gt;        {&lt;br/&gt;            &lt;span style='color:green'&gt;// Check the NewItems&lt;br/&gt;&lt;/span&gt;            &lt;span style='color:#2b91af'&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; newlist = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;List&lt;/span&gt;&amp;lt;T&amp;gt;();&lt;br/&gt;            &lt;span style='color:blue'&gt;if&lt;/span&gt; (e.NewItems != &lt;span style='color:blue'&gt;null&lt;/span&gt;)&lt;br/&gt;                &lt;span style='color:blue'&gt;foreach&lt;/span&gt; (T item &lt;span style='color:blue'&gt;in&lt;/span&gt; e.NewItems)&lt;br/&gt;                    &lt;span style='color:blue'&gt;if&lt;/span&gt; (_filter(item) == &lt;span style='color:blue'&gt;true&lt;/span&gt;)&lt;br/&gt;                        newlist.Add(item);&lt;br/&gt;&lt;br/&gt;            &lt;span style='color:green'&gt;// Check the OldItems&lt;br/&gt;&lt;/span&gt;            &lt;span style='color:#2b91af'&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; oldlist = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;List&lt;/span&gt;&amp;lt;T&amp;gt;();&lt;br/&gt;            &lt;span style='color:blue'&gt;if&lt;/span&gt; (e.OldItems != &lt;span style='color:blue'&gt;null&lt;/span&gt;)&lt;br/&gt;                &lt;span style='color:blue'&gt;foreach&lt;/span&gt; (T item &lt;span style='color:blue'&gt;in&lt;/span&gt; e.OldItems)&lt;br/&gt;                    &lt;span style='color:blue'&gt;if&lt;/span&gt; (_filter(item) == &lt;span style='color:blue'&gt;true&lt;/span&gt;)&lt;br/&gt;                        oldlist.Add(item);&lt;br/&gt;&lt;br/&gt;            &lt;span style='color:green'&gt;// Create the Add/Remove/Replace lists&lt;br/&gt;&lt;/span&gt;            &lt;span style='color:#2b91af'&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; addlist = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;List&lt;/span&gt;&amp;lt;T&amp;gt;();&lt;br/&gt;            &lt;span style='color:#2b91af'&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; removelist = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;List&lt;/span&gt;&amp;lt;T&amp;gt;();&lt;br/&gt;            &lt;span style='color:#2b91af'&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; replacelist = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;List&lt;/span&gt;&amp;lt;T&amp;gt;();&lt;br/&gt;&lt;br/&gt;            &lt;span style='color:green'&gt;// Fill the Add/Remove/Replace lists&lt;br/&gt;&lt;/span&gt;            &lt;span style='color:blue'&gt;foreach&lt;/span&gt; (T item &lt;span style='color:blue'&gt;in&lt;/span&gt; newlist)&lt;br/&gt;                &lt;span style='color:blue'&gt;if&lt;/span&gt; (oldlist.Contains(item))&lt;br/&gt;                    replacelist.Add(item);&lt;br/&gt;                &lt;span style='color:blue'&gt;else&lt;br/&gt;&lt;/span&gt;                    addlist.Add(item);&lt;br/&gt;            &lt;span style='color:blue'&gt;foreach&lt;/span&gt; (T item &lt;span style='color:blue'&gt;in&lt;/span&gt; oldlist)&lt;br/&gt;                &lt;span style='color:blue'&gt;if&lt;/span&gt; (newlist.Contains(item))&lt;br/&gt;                    &lt;span style='color:blue'&gt;continue&lt;/span&gt;;&lt;br/&gt;                &lt;span style='color:blue'&gt;else&lt;br/&gt;&lt;/span&gt;                    removelist.Add(item);&lt;br/&gt;&lt;br/&gt;            &lt;span style='color:green'&gt;// Send the corrected event&lt;br/&gt;&lt;/span&gt;            &lt;span style='color:blue'&gt;switch&lt;/span&gt; (e.Action)&lt;br/&gt;            {&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;NotifyCollectionChangedAction&lt;/span&gt;.Add:&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;NotifyCollectionChangedAction&lt;/span&gt;.Move:&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;NotifyCollectionChangedAction&lt;/span&gt;.Remove:&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;NotifyCollectionChangedAction&lt;/span&gt;.Replace:&lt;br/&gt;                    &lt;span style='color:blue'&gt;if&lt;/span&gt; (addlist.Count &amp;gt; 0)&lt;br/&gt;                        _collectionchanged(&lt;span style='color:blue'&gt;this&lt;/span&gt;, &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;NotifyCollectionChangedEventArgs&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;NotifyCollectionChangedAction&lt;/span&gt;.Add, addlist));&lt;br/&gt;                    &lt;span style='color:blue'&gt;if&lt;/span&gt; (replacelist.Count &amp;gt; 0)&lt;br/&gt;                        _collectionchanged(&lt;span style='color:blue'&gt;this&lt;/span&gt;, &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;NotifyCollectionChangedEventArgs&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;NotifyCollectionChangedAction&lt;/span&gt;.Replace, replacelist));&lt;br/&gt;                    &lt;span style='color:blue'&gt;if&lt;/span&gt; (removelist.Count &amp;gt; 0)&lt;br/&gt;                        _collectionchanged(&lt;span style='color:blue'&gt;this&lt;/span&gt;, &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;NotifyCollectionChangedEventArgs&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;NotifyCollectionChangedAction&lt;/span&gt;.Remove, removelist));&lt;br/&gt;                    &lt;span style='color:blue'&gt;break&lt;/span&gt;;&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;NotifyCollectionChangedAction&lt;/span&gt;.Reset:&lt;br/&gt;                    _collectionchanged(&lt;span style='color:blue'&gt;this&lt;/span&gt;, &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;NotifyCollectionChangedEventArgs&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;NotifyCollectionChangedAction&lt;/span&gt;.Reset));&lt;br/&gt;                    &lt;span style='color:blue'&gt;break&lt;/span&gt;;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;br /&gt;    &lt;/span&gt;&lt;/p&gt;&lt;p&gt;The enumerator starts from the first compliant element in the collection and each call to Next() makes the cursor move to the next valid filtered item.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;    &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;FilteredEnumerator&lt;/span&gt; : &lt;span style='color:#2b91af'&gt;IEnumerator&lt;/span&gt;&amp;lt;T&amp;gt;, &lt;span style='color:#2b91af'&gt;IEnumerator&lt;br/&gt;&lt;/span&gt;    {&lt;br/&gt;        &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;FilteredObservableCollection&lt;/span&gt;&amp;lt;T&amp;gt; _filteredcollection;&lt;br/&gt;        &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;IEnumerator&lt;/span&gt;&amp;lt;T&amp;gt; _enumerator;&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;public&lt;/span&gt; FilteredEnumerator(&lt;span style='color:#2b91af'&gt;FilteredObservableCollection&lt;/span&gt;&amp;lt;T&amp;gt; filteredcollection, &lt;span style='color:#2b91af'&gt;IEnumerator&lt;/span&gt;&amp;lt;T&amp;gt; enumerator)&lt;br/&gt;        {&lt;br/&gt;            _filteredcollection = filteredcollection;&lt;br/&gt;            _enumerator = enumerator;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;public&lt;/span&gt; T Current&lt;br/&gt;        {&lt;br/&gt;            &lt;span style='color:blue'&gt;get&lt;br/&gt;&lt;/span&gt;            {&lt;br/&gt;                &lt;span style='color:blue'&gt;if&lt;/span&gt; (_filteredcollection.Filter == &lt;span style='color:blue'&gt;null&lt;/span&gt;)&lt;br/&gt;                    &lt;span style='color:blue'&gt;return&lt;/span&gt; _enumerator.Current;&lt;br/&gt;                &lt;span style='color:blue'&gt;else&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;if&lt;/span&gt; (_filteredcollection.Filter(_enumerator.Current) == &lt;span style='color:blue'&gt;false&lt;/span&gt;)&lt;br/&gt;                    &lt;span style='color:blue'&gt;throw&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;InvalidOperationException&lt;/span&gt;();&lt;br/&gt;                &lt;span style='color:blue'&gt;else&lt;br/&gt;&lt;/span&gt;                    &lt;span style='color:blue'&gt;return&lt;/span&gt; _enumerator.Current;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;void&lt;/span&gt; Dispose()&lt;br/&gt;        {&lt;br/&gt;            _enumerator.Dispose();&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;object&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;IEnumerator&lt;/span&gt;.Current&lt;br/&gt;        {&lt;br/&gt;            &lt;span style='color:blue'&gt;get&lt;/span&gt; { &lt;span style='color:blue'&gt;return&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;this&lt;/span&gt;.Current; }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;bool&lt;/span&gt; MoveNext()&lt;br/&gt;        {&lt;br/&gt;            &lt;span style='color:blue'&gt;while&lt;/span&gt; (&lt;span style='color:blue'&gt;true&lt;/span&gt;)&lt;br/&gt;            {&lt;br/&gt;                &lt;span style='color:blue'&gt;if&lt;/span&gt; (_enumerator.MoveNext() == &lt;span style='color:blue'&gt;false&lt;/span&gt;)&lt;br/&gt;                    &lt;span style='color:blue'&gt;return&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;false&lt;/span&gt;;&lt;br/&gt;                &lt;span style='color:blue'&gt;if&lt;/span&gt; (_filteredcollection.Filter == &lt;span style='color:blue'&gt;null&lt;br/&gt;&lt;/span&gt;                    || _filteredcollection.Filter(_enumerator.Current) == &lt;span style='color:blue'&gt;true&lt;/span&gt;)&lt;br/&gt;                    &lt;span style='color:blue'&gt;return&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;true&lt;/span&gt;;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;void&lt;/span&gt; Reset()&lt;br/&gt;        {&lt;br/&gt;            _enumerator.Reset();&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br /&gt;    &lt;/span&gt;&lt;/p&gt;&lt;p&gt;It's worked well so far but a lot remains to be done. I need to optimize the code to avoid for example having to calculate the Count at every call. I need to test all the possible collection manipulation and see if the CollectionChanged event is processed correctly. I need to implement the missing Move() method. I need to test multi-threading.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I've made the code available for download as part of a sample project that displays a list of integers and two subsets of multiples of 2 and of 3. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;Data&lt;/span&gt; : &lt;span style='color:#2b91af'&gt;DependencyObject&lt;br/&gt;&lt;/span&gt;{&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;readonly&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt; FullListProperty =&lt;br/&gt;       &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt;.Register(&lt;span style='color:#a31515'&gt;"FullList"&lt;/span&gt;, &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;ObservableCollection&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt;), &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;Data&lt;/span&gt;));&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;readonly&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt; List_2Property =&lt;br/&gt;       &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt;.Register(&lt;span style='color:#a31515'&gt;"List_2"&lt;/span&gt;, &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;FilteredObservableCollection&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt;), &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;Data&lt;/span&gt;));&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;readonly&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt; List_3Property =&lt;br/&gt;       &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt;.Register(&lt;span style='color:#a31515'&gt;"List_3"&lt;/span&gt;, &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;FilteredObservableCollection&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt;), &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;Data&lt;/span&gt;));&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;ObservableCollection&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt; FullList&lt;br/&gt;    {&lt;br/&gt;        &lt;span style='color:blue'&gt;get&lt;/span&gt; { &lt;span style='color:blue'&gt;return&lt;/span&gt; (&lt;span style='color:#2b91af'&gt;ObservableCollection&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt;)GetValue(FullListProperty); }&lt;br/&gt;        &lt;span style='color:blue'&gt;set&lt;/span&gt; { SetValue(FullListProperty, &lt;span style='color:blue'&gt;value&lt;/span&gt;); }&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;FilteredObservableCollection&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt; List_2&lt;br/&gt;    {&lt;br/&gt;        &lt;span style='color:blue'&gt;get&lt;/span&gt; { &lt;span style='color:blue'&gt;return&lt;/span&gt; (&lt;span style='color:#2b91af'&gt;FilteredObservableCollection&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt;)GetValue(List_2Property); }&lt;br/&gt;        &lt;span style='color:blue'&gt;set&lt;/span&gt; { SetValue(List_2Property, &lt;span style='color:blue'&gt;value&lt;/span&gt;); }&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;FilteredObservableCollection&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt; List_3&lt;br/&gt;    {&lt;br/&gt;        &lt;span style='color:blue'&gt;get&lt;/span&gt; { &lt;span style='color:blue'&gt;return&lt;/span&gt; (&lt;span style='color:#2b91af'&gt;FilteredObservableCollection&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt;)GetValue(List_3Property); }&lt;br/&gt;        &lt;span style='color:blue'&gt;set&lt;/span&gt; { SetValue(List_3Property, &lt;span style='color:blue'&gt;value&lt;/span&gt;); }&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt; Data()&lt;br/&gt;    {&lt;br/&gt;        FullList = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;ObservableCollection&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt;();&lt;br/&gt;        List_2 = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;FilteredObservableCollection&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt;(FullList);&lt;br/&gt;        List_3 = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;FilteredObservableCollection&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt;(FullList);&lt;br/&gt;&lt;br/&gt;        List_2.Filter = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;Predicate&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt;(Filter_2);&lt;br/&gt;        List_3.Filter = &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:#2b91af'&gt;Predicate&lt;/span&gt;&amp;lt;&lt;span style='color:blue'&gt;int&lt;/span&gt;&amp;gt;(Filter_3);&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;bool&lt;/span&gt; Filter_2(&lt;span style='color:blue'&gt;int&lt;/span&gt; x) { &lt;span style='color:blue'&gt;return&lt;/span&gt; x % 2 == 0; }&lt;br/&gt;    &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;     &lt;span style='color:blue'&gt;bool&lt;/span&gt; Filter_3(&lt;span style='color:blue'&gt;int&lt;/span&gt; x) { &lt;span style='color:blue'&gt;return&lt;/span&gt; x % 3 == 0; }&lt;br/&gt;}&lt;br/&gt;&lt;br /&gt;    &lt;/span&gt;&lt;/p&gt;&lt;p&gt;I've used a DependencyObject and DependencyProperties but it wasn't necessary to use the FilteredObservableCollection.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;   &lt;/p&gt;&lt;p&gt;Download the project source code here: &lt;a href='http://blog-mridey.appspot.com/FilteredObservableCollection.zip'&gt;Download&lt;/a&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-5742281859889603640?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/JAcDzw2vn3Y" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/JAcDzw2vn3Y/filtered-observablecollection.html</link><author>noreply@blogger.com (Marc Ridey)</author><thr:total>5</thr:total><feedburner:origLink>http://blog.mridey.com/2009/05/filtered-observablecollection.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-7940938345856665235</guid><pubDate>Mon, 04 May 2009 12:19:00 +0000</pubDate><atom:updated>2009-05-04T22:19:24.392+10:00</atom:updated><title>Attached DependencyProperty</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/me3FEw3SB4jMy8dbXCHfgGt_cVM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/me3FEw3SB4jMy8dbXCHfgGt_cVM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/me3FEw3SB4jMy8dbXCHfgGt_cVM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/me3FEw3SB4jMy8dbXCHfgGt_cVM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;span xmlns=''&gt;&lt;p&gt;In my previous blog on &lt;a href='http://www.mridey.com/blog/Lists/Posts/Post.aspx?ID=4'&gt;DependencyProperty&lt;/a&gt;, I talked about how to create properties in objects using DependencyProperty and DependencyObject, to have support for Databinding, defaults, expressions, events and validations.&lt;br/&gt;But on some occasions, you want to assign a parent object needs to assign a property to the children objects, regardless of the type of object.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Traditionally, this has been done using base class and inheritance. For example, if you wanted to create a panel control that understands commands, you would need to create a base class 'CmdControl" something like this:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;partial&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;CmdControl&lt;/span&gt; : &lt;span style='color:#2b91af'&gt;UserControl&lt;br/&gt;&lt;/span&gt;{&lt;br/&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt; CmdControl()&lt;br/&gt;    {&lt;br/&gt;        InitializeComponent();&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;string&lt;/span&gt; _cmd;&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;string&lt;/span&gt; Cmd&lt;br/&gt;    {&lt;br/&gt;        &lt;span style='color:blue'&gt;get&lt;br/&gt;&lt;/span&gt;        {&lt;br/&gt;            &lt;span style='color:blue'&gt;return&lt;/span&gt; _cmd;&lt;br/&gt;        }&lt;br/&gt;        &lt;span style='color:blue'&gt;set&lt;br/&gt;&lt;/span&gt;        {&lt;br/&gt;            _cmd = &lt;span style='color:blue'&gt;value&lt;/span&gt;;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Then you would create all your controls derived from CmdControl, thus ensuring that each control has a Cmd property:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;partial&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;MyControl&lt;/span&gt; : &lt;span style='color:#2b91af'&gt;CmdControl&lt;br/&gt;&lt;/span&gt;{&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt; MyControl()&lt;br/&gt;    {&lt;br/&gt;        &lt;span style='color:blue'&gt;this&lt;/span&gt;.Cmd = "Do this";&lt;br/&gt;&lt;br/&gt;        InitializeComponent();&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;But this method did not allow the use of existing controls or classes. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;With attached properties, a property can be set for each child control but the storage of the value is handled by the parent class.&lt;br/&gt;Let's see how to declare the Grid control and the Cmd attached property:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;partial&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;MyPanel&lt;/span&gt; : &lt;span style='color:#2b91af'&gt;System.Windows.Controls.Grid&lt;br/&gt;&lt;/span&gt;{&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt; MyPanel()&lt;br/&gt;    {&lt;br/&gt;        InitializeComponent();&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;string&lt;/span&gt; GetCmd(DependencyObject obj)&lt;br/&gt;    {&lt;br/&gt;        &lt;span style='color:blue'&gt;return&lt;/span&gt; (&lt;span style='color:blue'&gt;string&lt;/span&gt;)obj.GetValue(CmdProperty);&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;void&lt;/span&gt; SetCmd(DependencyObject obj, &lt;span style='color:blue'&gt;string&lt;/span&gt; value)&lt;br/&gt;    {&lt;br/&gt;        obj.SetValue(CmdProperty, value);&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;readonly&lt;/span&gt; DependencyProperty CmdProperty =&lt;br/&gt;        DependencyProperty.RegisterAttached(&lt;span style='color:#a31515'&gt;"Cmd"&lt;/span&gt;, &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:blue'&gt;string&lt;/span&gt;), &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;MyPanel&lt;/span&gt;), &lt;span style='color:blue'&gt;new&lt;/span&gt; UIPropertyMetadata("Open"));&lt;br/&gt;}&lt;br/&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;In XAML, the panel is used as per my previous blog:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Window&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;x:Class&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;WPF2.Window1&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;xmlns&lt;/span&gt;&lt;span style='color:blue'&gt;=http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/span&gt;&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;xmlns:x&lt;/span&gt;&lt;span style='color:blue'&gt;=http://schemas.microsoft.com/winfx/2006/xaml&lt;/span&gt;&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;xmlns:AppCode&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;clr-namespace:WPF2&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;Title&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;WPF2&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Height&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;263&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Width&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;239&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &amp;gt;&lt;br/&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;AppCode:MyPanel&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;x:Name&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Panel1&lt;/span&gt;"&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Button&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Name&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Button1&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Height&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;23&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Margin&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;50,0,50,0&lt;/span&gt;"&lt;span style='color:blue'&gt; &amp;gt;&lt;/span&gt;Button1&lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Button&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Button&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Name&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Button2&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Height&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;23&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Margin&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;50,50,50,0&lt;/span&gt;"&lt;span style='color:blue'&gt; &amp;gt;&lt;/span&gt;Button2&lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Button&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;    &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;AppCode:MyPanel&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Window&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;&lt;br /&gt;					&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;You can then programmatically assign a command value to any child control:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;partial&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Window1&lt;/span&gt; : System.Windows.&lt;span style='color:#2b91af'&gt;Window&lt;br/&gt;&lt;/span&gt;{&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt; Window1()&lt;br/&gt;    {&lt;br/&gt;        InitializeComponent();&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:#2b91af'&gt;MyPanel&lt;/span&gt;.SetCmd(Button1, &lt;span style='color:#a31515'&gt;"Open 1"&lt;/span&gt;);&lt;br/&gt;        &lt;span style='color:#2b91af'&gt;MyPanel&lt;/span&gt;.SetCmd(Button2, &lt;span style='color:#a31515'&gt;"Close 1"&lt;/span&gt;);&lt;br/&gt;&lt;br/&gt;        Button1.Click += &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;RoutedEventHandler&lt;/span&gt;(Button_Click);&lt;br/&gt;        Button2.Click += &lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;RoutedEventHandler&lt;/span&gt;(Button_Click);&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;void&lt;/span&gt; Button_Click(&lt;span style='color:blue'&gt;object&lt;/span&gt; sender, &lt;span style='color:#2b91af'&gt;RoutedEventArgs&lt;/span&gt; e)&lt;br/&gt;    {&lt;br/&gt;        &lt;span style='color:#2b91af'&gt;MessageBox&lt;/span&gt;.Show(&lt;span style='color:#a31515'&gt;"My Command is "&lt;/span&gt; + &lt;span style='color:#2b91af'&gt;MyPanel&lt;/span&gt;.GetCmd(sender &lt;span style='color:blue'&gt;as&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;DependencyObject&lt;/span&gt;));&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Or you can do the same thing in XAML:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Window&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;x:Class&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;WPF2.Window1&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;xmlns&lt;/span&gt;&lt;span style='color:blue'&gt;=http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/span&gt;&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;xmlns:x&lt;/span&gt;&lt;span style='color:blue'&gt;=http://schemas.microsoft.com/winfx/2006/xaml&lt;/span&gt;&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;xmlns:AppCode&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;clr-namespace:WPF2&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;Title&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;WPF2&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Height&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;263&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Width&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;239&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &amp;gt;&lt;br/&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;AppCode:MyPanel&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;x:Name&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Panel1&lt;/span&gt;"&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Button&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;AppCode:MyPanel.Cmd&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Open 1&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Click&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Button_Click&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Height&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;23&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Margin&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;50,0,50,0&lt;/span&gt;"&lt;span style='color:blue'&gt; &amp;gt;&lt;/span&gt;Button1&lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Button&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Button&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;AppCode:MyPanel.Cmd&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Close 1&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Click&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Button_Click&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Height&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;23&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Margin&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;50,50,50,0&lt;/span&gt;"&lt;span style='color:blue'&gt; &amp;gt;&lt;/span&gt;Button2&lt;span style='color:blue'&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Button&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;    &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;AppCode:MyPanel&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Window&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;&lt;br /&gt;					&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;When you launch the application, and you click on either button, you get a message box with the text of the command assigned to that button.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;More information on attached properties can be found &lt;a href='http://msdn2.microsoft.com/en-us/library/ms749011.aspx'&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-7940938345856665235?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/E6vAUuyix7I" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/E6vAUuyix7I/attached-dependencyproperty.html</link><author>noreply@blogger.com (Marc Ridey)</author><thr:total>0</thr:total><feedburner:origLink>http://blog.mridey.com/2009/05/attached-dependencyproperty.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-7013471144650405722</guid><pubDate>Mon, 04 May 2009 12:19:00 +0000</pubDate><atom:updated>2009-05-04T22:19:12.331+10:00</atom:updated><title>DependencyProperty and DependencyObject</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/nedq6L0Gt_bRlJb-VK7dHe04LPE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nedq6L0Gt_bRlJb-VK7dHe04LPE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/nedq6L0Gt_bRlJb-VK7dHe04LPE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/nedq6L0Gt_bRlJb-VK7dHe04LPE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;span xmlns=''&gt;&lt;p&gt;Up until now, you would create properties in a class using this syntax:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;MyObject&lt;br/&gt;&lt;/span&gt;{&lt;br/&gt;    &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;string&lt;/span&gt; MyPropertyValue;&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;string&lt;/span&gt; MyProperty&lt;br/&gt;    {&lt;br/&gt;        &lt;span style='color:blue'&gt;set&lt;br/&gt;&lt;/span&gt;        {&lt;br/&gt;            MyPropertyValue = &lt;span style='color:blue'&gt;value&lt;/span&gt;;&lt;br/&gt;        }&lt;br/&gt;        &lt;span style='color:blue'&gt;get&lt;br/&gt;&lt;/span&gt;        {&lt;br/&gt;            &lt;span style='color:blue'&gt;return&lt;/span&gt; MyPropertyValue;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/span&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;This is fine but then you have a lot of code to add to handle additional features such as PropertyChanged event, data binding, default value, validation.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;DependencyObject and DependencyProperty provide a simpler way to implement properties and provide directly off the shelf:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;DataBinding&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Events&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Validation&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Default Value&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As well as elements more specific to Windows Foundation and .NET 3.0:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Animation&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Style&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Attached properties&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Expressions&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So let's see how to use these new classes. &lt;br/&gt;First we create a class similar to the one above:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt; : &lt;span style='color:#2b91af'&gt;DependencyObject&lt;br/&gt;&lt;/span&gt;{&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt; FloorProperty =&lt;br/&gt;        &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt;.Register(&lt;span style='color:#a31515'&gt;"Floor"&lt;/span&gt;, &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:blue'&gt;int&lt;/span&gt;), &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt;));&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;int&lt;/span&gt; Floor&lt;br/&gt;    {&lt;br/&gt;        &lt;span style='color:blue'&gt;get&lt;/span&gt; { &lt;span style='color:blue'&gt;return&lt;/span&gt; (&lt;span style='color:blue'&gt;int&lt;/span&gt;)GetValue(FloorProperty); }&lt;br/&gt;        &lt;span style='color:blue'&gt;set&lt;/span&gt; { SetValue(FloorProperty, &lt;span style='color:blue'&gt;value&lt;/span&gt;); }&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/span&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;I have a class Lift with a property called Floor. Already I can implement many of the WPF feature. The Lift class is ready for DataBinding, the Floor property will accept expressions to be set and can be used as part of another expression.&lt;br/&gt;Let's look at this simple XAML code:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Window&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;x:Class&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;TestWPF1.Window1&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;xmlns&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;xmlns:x&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;http://schemas.microsoft.com/winfx/2006/xaml&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;xmlns:AppCode&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;clr-namespace:TestWPF1&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;Title&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;TestWPF1&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Height&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;300&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Width&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;300&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &amp;gt;&lt;br/&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Window.Resources&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;AppCode:Lift&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;x:Key&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Lift1&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Floor&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;1&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;    &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Window.Resources&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Orientation&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Horizontal&lt;/span&gt;"&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;{Binding Path=Floor}&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel.DataContext&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;            &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Binding&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Source&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;{StaticResource Lift1}&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;        &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel.DataContext&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;    &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Window&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;&lt;br /&gt;					&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;I created an instance of Lift in XAML and databound it to the StackPanel.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Still I rely on the user to set the Floor value to a correct value. Why not assign a default value:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt; FloorProperty =&lt;br/&gt;        &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt;.Register(&lt;span style='color:#a31515'&gt;"Floor"&lt;/span&gt;, &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:blue'&gt;int&lt;/span&gt;),&lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt;),&lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;PropertyMetadata&lt;/span&gt;(0));&lt;br/&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;By setting the default value in the metadata, I can now create an instance of the Lift class without specifying the value for Floor:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;AppCode:Lift&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;x:Key&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Lift1&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;&lt;br /&gt;					&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Now I'd like to display the kind of goods for sale on the floor of that building. I add a second property to my class called "Goods".&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt; GoodsProperty =&lt;br/&gt;        &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt;.Register(&lt;span style='color:#a31515'&gt;"Goods"&lt;/span&gt;, &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:blue'&gt;string&lt;/span&gt;), &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt;));&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;string&lt;/span&gt; Goods&lt;br/&gt;    {&lt;br/&gt;        &lt;span style='color:blue'&gt;get&lt;/span&gt; { &lt;span style='color:blue'&gt;return&lt;/span&gt; (&lt;span style='color:blue'&gt;string&lt;/span&gt;)GetValue(GoodsProperty); }&lt;br/&gt;        &lt;span style='color:blue'&gt;set&lt;/span&gt; { SetValue(GoodsProperty, &lt;span style='color:blue'&gt;value&lt;/span&gt;); }&lt;br/&gt;    }&lt;br/&gt;&lt;/span&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;And I can use it directly in XAML:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;AppCode:Lift&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;x:Key&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Lift1&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Floor&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;1&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Goods&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Perfumes&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;    …&lt;br/&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;{Binding Path=Floor}&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;: &lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;{Binding Path=Goods}&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;But I'd like set the goods value directly in my class according to the floor set. I can do that by handling the PropertyChanged event on the Floor property. I just expand a bit the property definition to get the Changed event:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;        &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt; FloorProperty =&lt;br/&gt;            &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt;.Register(&lt;span style='color:#a31515'&gt;"Floor"&lt;/span&gt;, &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:blue'&gt;int&lt;/span&gt;),&lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt;),&lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;PropertyMetadata&lt;/span&gt;(0,&lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;PropertyChangedCallback&lt;/span&gt;(OnFloorChanged));&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;void&lt;/span&gt; OnFloorChanged(&lt;span style='color:#2b91af'&gt;DependencyObject&lt;/span&gt; obj, &lt;span style='color:#2b91af'&gt;DependencyPropertyChangedEventArgs&lt;/span&gt; arg) &lt;br/&gt;        {&lt;br/&gt;            &lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt; l = (&lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt;)obj;&lt;br/&gt;            &lt;span style='color:blue'&gt;switch&lt;/span&gt; (l.Floor)&lt;br/&gt;            {&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt; 0:&lt;br/&gt;                    l.Goods = &lt;span style='color:#a31515'&gt;"Books"&lt;/span&gt;;&lt;br/&gt;                    &lt;span style='color:blue'&gt;break&lt;/span&gt;;&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt; 1:&lt;br/&gt;                    l.Goods = &lt;span style='color:#a31515'&gt;"Perfumes"&lt;/span&gt;;&lt;br/&gt;                    &lt;span style='color:blue'&gt;break&lt;/span&gt;;&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt; 2:&lt;br/&gt;                    l.Goods = &lt;span style='color:#a31515'&gt;"Toys"&lt;/span&gt;;&lt;br/&gt;                    &lt;span style='color:blue'&gt;break&lt;/span&gt;;&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt; 3:&lt;br/&gt;                    l.Goods = &lt;span style='color:#a31515'&gt;"Kitchenware"&lt;/span&gt;;&lt;br/&gt;                    &lt;span style='color:blue'&gt;break&lt;/span&gt;;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;So in XAML, it looks like:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;AppCode:Lift&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;x:Key&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Lift1&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Floor&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;1&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;    …&lt;br/&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;{Binding Path=Floor}&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;: &lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;{Binding Path=Goods}&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;&lt;br /&gt;					&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;I no longer have to supply the Goods value, it's set when the Floor value is modified.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;Ok so we've looked at Databinding, Property Changed, Default value, now we need validation. My building doesn't have an infinite number of floors so I'd like to restrict the Floor value to between 0 and 3.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;I can add validation by handling the Validate event:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;    &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt; FloorProperty =&lt;br/&gt;        &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt;.Register((&lt;span style='color:#a31515'&gt;"Floor"&lt;/span&gt;, &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:blue'&gt;int&lt;/span&gt;),&lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt;),&lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;PropertyMetadata&lt;/span&gt;(0,&lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;PropertyChangedCallback&lt;/span&gt;(OnFloorChanged)),&lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;ValidateValueCallback&lt;/span&gt;(OnFloorValidate));&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;bool&lt;/span&gt; OnFloorValidate(&lt;span style='color:blue'&gt;object&lt;/span&gt; obj) &lt;br/&gt;        {&lt;br/&gt;            &lt;span style='color:blue'&gt;return&lt;/span&gt; obj &lt;span style='color:blue'&gt;is&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;int&lt;/span&gt; &amp;amp;&amp;amp; (&lt;span style='color:blue'&gt;int&lt;/span&gt;)obj &amp;gt;= 0 &amp;amp;&amp;amp; (&lt;span style='color:blue'&gt;int&lt;/span&gt;)obj &amp;lt;= 3;&lt;br/&gt;        }&lt;br/&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This not only validates that the value is between 0 and 3 but also checks that the value is actually an integer. An exception is thrown if you try to set the property to an incorrect value.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;The final class looks like:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;    &lt;span style='color:blue'&gt;class&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt; : &lt;span style='color:#2b91af'&gt;DependencyObject&lt;br/&gt;&lt;/span&gt;    {&lt;br/&gt;        &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt; FloorProperty =&lt;br/&gt;            &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt;.Register((&lt;span style='color:#a31515'&gt;"Floor"&lt;/span&gt;, &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:blue'&gt;int&lt;/span&gt;),&lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt;),&lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;PropertyMetadata&lt;/span&gt;(0,&lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;PropertyChangedCallback&lt;/span&gt;(OnFloorChanged)),&lt;span style='color:blue'&gt;new&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;ValidateValueCallback&lt;/span&gt;(OnFloorValidate));&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;void&lt;/span&gt; OnFloorChanged(&lt;span style='color:#2b91af'&gt;DependencyObject&lt;/span&gt; obj, &lt;span style='color:#2b91af'&gt;DependencyPropertyChangedEventArgs&lt;/span&gt; arg) &lt;br/&gt;        {&lt;br/&gt;            &lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt; l = (&lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt;)obj;&lt;br/&gt;            &lt;span style='color:blue'&gt;switch&lt;/span&gt; (l.Floor)&lt;br/&gt;            {&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt; 0:&lt;br/&gt;                    l.Goods = &lt;span style='color:#a31515'&gt;"Books"&lt;/span&gt;;&lt;br/&gt;                    &lt;span style='color:blue'&gt;break&lt;/span&gt;;&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt; 1:&lt;br/&gt;                    l.Goods = &lt;span style='color:#a31515'&gt;"Perfumes"&lt;/span&gt;;&lt;br/&gt;                    &lt;span style='color:blue'&gt;break&lt;/span&gt;;&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt; 2:&lt;br/&gt;                    l.Goods = &lt;span style='color:#a31515'&gt;"Toys"&lt;/span&gt;;&lt;br/&gt;                    &lt;span style='color:blue'&gt;break&lt;/span&gt;;&lt;br/&gt;                &lt;span style='color:blue'&gt;case&lt;/span&gt; 3:&lt;br/&gt;                    l.Goods = &lt;span style='color:#a31515'&gt;"Kitchenware"&lt;/span&gt;;&lt;br/&gt;                    &lt;span style='color:blue'&gt;break&lt;/span&gt;;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;private&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;bool&lt;/span&gt; OnFloorValidate(&lt;span style='color:blue'&gt;object&lt;/span&gt; obj) &lt;br/&gt;        {&lt;br/&gt;            &lt;span style='color:blue'&gt;return&lt;/span&gt; obj &lt;span style='color:blue'&gt;is&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;int&lt;/span&gt; &amp;amp;&amp;amp; (&lt;span style='color:blue'&gt;int&lt;/span&gt;)obj &amp;gt;= 0 &amp;amp;&amp;amp; (&lt;span style='color:blue'&gt;int&lt;/span&gt;)obj &amp;lt;= 3;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;int&lt;/span&gt; Floor&lt;br/&gt;        {&lt;br/&gt;            &lt;span style='color:blue'&gt;get&lt;/span&gt; { &lt;span style='color:blue'&gt;return&lt;/span&gt; (&lt;span style='color:blue'&gt;int&lt;/span&gt;)GetValue(FloorProperty); }&lt;br/&gt;            &lt;span style='color:blue'&gt;set&lt;/span&gt; { SetValue(FloorProperty, &lt;span style='color:blue'&gt;value&lt;/span&gt;); }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;static&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt; GoodsProperty =&lt;br/&gt;        &lt;span style='color:#2b91af'&gt;DependencyProperty&lt;/span&gt;.Register(&lt;span style='color:#a31515'&gt;"Goods"&lt;/span&gt;, &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:blue'&gt;string&lt;/span&gt;), &lt;span style='color:blue'&gt;typeof&lt;/span&gt;(&lt;span style='color:#2b91af'&gt;Lift&lt;/span&gt;));&lt;br/&gt;&lt;br/&gt;        &lt;span style='color:blue'&gt;public&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;string&lt;/span&gt; Goods&lt;br/&gt;        {&lt;br/&gt;            &lt;span style='color:blue'&gt;get&lt;/span&gt; { &lt;span style='color:blue'&gt;return&lt;/span&gt; (&lt;span style='color:blue'&gt;string&lt;/span&gt;)GetValue(GoodsProperty); }&lt;br/&gt;            &lt;span style='color:blue'&gt;set&lt;/span&gt; { SetValue(GoodsProperty, &lt;span style='color:blue'&gt;value&lt;/span&gt;); }&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;/span&gt;&lt;br /&gt;			&lt;/p&gt;&lt;p&gt;And the XAML:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:10pt'&gt;&lt;span style='color:blue'&gt;&amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Window&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;x:Class&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;TestWPF1.Window1&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;xmlns&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;http://schemas.microsoft.com/winfx/2006/xaml/presentation&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;xmlns:x&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;http://schemas.microsoft.com/winfx/2006/xaml&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;xmlns:AppCode&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;clr-namespace:TestWPF1&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &lt;/span&gt;&lt;span style='color:red'&gt;Title&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;TestWPF1&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Height&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;300&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Width&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;300&lt;/span&gt;"&lt;br/&gt;&lt;span style='color:blue'&gt;    &amp;gt;&lt;br/&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Window.Resources&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;AppCode:Lift&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;x:Key&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Lift1&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Floor&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;1&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;AppCode:Lift&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;x:Key&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Lift2&lt;/span&gt;"&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Floor&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;3&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;    &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Window.Resources&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;    &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Orientation&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Vertical&lt;/span&gt;"&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Orientation&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Horizontal&lt;/span&gt;"&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;            &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;{Binding Path=Floor}&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;            &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;, &lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;            &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;{Binding Path=Goods}&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;            &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel.DataContext&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;                &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Binding&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Source&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;{StaticResource Lift1}&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;            &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel.DataContext&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;        &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;        &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Orientation&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;Horizontal&lt;/span&gt;"&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;            &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;{Binding Path=Floor}&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;            &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;, &lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;            &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;TextBlock&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Text&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;{Binding Path=Goods}&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;            &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel.DataContext&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;                &amp;lt;&lt;/span&gt;&lt;span style='color:#a31515'&gt;Binding&lt;/span&gt;&lt;span style='color:blue'&gt;&lt;br /&gt;					&lt;/span&gt;&lt;span style='color:red'&gt;Source&lt;/span&gt;&lt;span style='color:blue'&gt;=&lt;/span&gt;"&lt;span style='color:blue'&gt;{StaticResource Lift2}&lt;/span&gt;"&lt;span style='color:blue'&gt; /&amp;gt;&lt;br/&gt;            &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel.DataContext&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;        &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;    &amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;StackPanel&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;&amp;lt;/&lt;/span&gt;&lt;span style='color:#a31515'&gt;Window&lt;/span&gt;&lt;span style='color:blue'&gt;&amp;gt;&lt;br/&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-7013471144650405722?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/TJkeI3UAuis" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/TJkeI3UAuis/dependencyproperty-and-dependencyobject.html</link><author>noreply@blogger.com (Marc Ridey)</author><thr:total>2</thr:total><feedburner:origLink>http://blog.mridey.com/2009/05/dependencyproperty-and-dependencyobject.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-6259562913746865237.post-4134453226310325991</guid><pubDate>Mon, 04 May 2009 12:17:00 +0000</pubDate><atom:updated>2009-05-04T22:17:40.082+10:00</atom:updated><title>String and Custom Aggregations using CTE and Recursive Queries</title><description>&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/D_DlobgzbnkZBOxcGmUMhTYwf3k/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D_DlobgzbnkZBOxcGmUMhTYwf3k/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/D_DlobgzbnkZBOxcGmUMhTYwf3k/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D_DlobgzbnkZBOxcGmUMhTYwf3k/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;span xmlns=''&gt;&lt;p&gt;You'll all be familiar with normal aggregation. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;For example I can get the number of subcategories per category in AdventureWorks:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:9pt'&gt;&lt;span style='color:blue'&gt;SELECT&lt;/span&gt; c&lt;span style='color:gray'&gt;.&lt;/span&gt;Name&lt;span style='color:gray'&gt;,&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:fuchsia'&gt;COUNT&lt;/span&gt;&lt;span style='color:gray'&gt;(*)&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;as&lt;/span&gt; SubCategoryCount&lt;br/&gt;&lt;span style='color:blue'&gt;FROM&lt;/span&gt; Production&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductCategory c&lt;br/&gt;&lt;span style='color:gray'&gt;JOIN&lt;/span&gt; Production&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductSubCategory s&lt;br/&gt;&lt;span style='color:blue'&gt;ON&lt;/span&gt; c&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductCategoryID &lt;span style='color:gray'&gt;=&lt;/span&gt; s&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductCategoryID&lt;br/&gt;&lt;span style='color:blue'&gt;GROUP&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;BY&lt;/span&gt; c&lt;span style='color:gray'&gt;.&lt;/span&gt;Name&lt;br/&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Which returns:&lt;br /&gt;&lt;/p&gt;&lt;div&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:319px'/&gt;&lt;col style='width:319px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr style='background: white'&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #c0504d 3.0pt; border-right:  none'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #c0504d 3.0pt; border-right:  none'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;&lt;strong&gt;SubCategoryCount&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style='background: #2c4c74; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #2c4c74 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:white; font-family:Courier New; font-size:8pt'&gt;Accessories&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #a7bfde; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid #4f81bd 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;12&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style='background: #2c4c74; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #2c4c74 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:white; font-family:Courier New; font-size:8pt'&gt;Bikes&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #edf2f8; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid #4f81bd 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;3&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style='background: #2c4c74; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #2c4c74 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:white; font-family:Courier New; font-size:8pt'&gt;Clothing&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #a7bfde; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid #4f81bd 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;8&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style='background: #2c4c74; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  none; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:white; font-family:Courier New; font-size:8pt'&gt;Components&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #edf2f8; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #4f81bd 0.5pt; border-right:  solid #4f81bd 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;14&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;SQL 2005 supports 13 aggregation functions: AVG, CHECKSUM, CHECKSUM_AGG, COUNT, COUNT_BIG, GROUPING, MAX, MIN, SUM, STDEV, STDEVP, VAR and VARP but nothing to aggregate strings.&lt;br/&gt;You can create custom CLR aggregation functions but on some occasions, a simple SQL recursive query may be able to do what you need.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Let's have a look first at a case that doesn't require recursive queries.&lt;br/&gt;Let's create a comma delimited string of all the available categories.&lt;br/&gt;The data comes from the Product.ProductCategory table:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-size:9pt'&gt;&lt;span style='color:blue; font-family:Courier New'&gt;select&lt;/span&gt;&lt;span style='font-family:Courier New'&gt;&lt;br /&gt;						&lt;span style='color:gray'&gt;*&lt;/span&gt;&lt;br /&gt;						&lt;span style='color:blue'&gt;from&lt;/span&gt; Production&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductCategory&lt;br/&gt;&lt;/span&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;And returns&lt;br /&gt;&lt;/p&gt;&lt;div&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:160px'/&gt;&lt;col style='width:160px'/&gt;&lt;col style='width:160px'/&gt;&lt;col style='width:160px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr style='background: white'&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #c0504d 3.0pt; border-right:  none'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;&lt;strong&gt;ProductCategoryID&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #c0504d 3.0pt; border-right:  none'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #c0504d 3.0pt; border-right:  none'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;&lt;strong&gt;rowguid&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #c0504d 3.0pt; border-right:  none'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;&lt;strong&gt;ModifiedDate&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style='background: #2c4c74; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #2c4c74 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:white; font-family:Courier New; font-size:8pt'&gt;1&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #a7bfde; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;Bikes&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #a7bfde; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;CFBDA25C-DF71-47A7-B81B-64EE161AA37C&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #a7bfde; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid #4f81bd 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;1998-06-01 00:00:00.000&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style='background: #2c4c74; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #2c4c74 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:white; font-family:Courier New; font-size:8pt'&gt;2&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #edf2f8; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;Components&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #edf2f8; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;C657828D-D808-4ABA-91A3-AF2CE02300E9&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #edf2f8; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid #4f81bd 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;1998-06-01 00:00:00.000&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style='background: #2c4c74; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #2c4c74 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:white; font-family:Courier New; font-size:8pt'&gt;3&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #a7bfde; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;Clothing&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #a7bfde; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;10A7C342-CA82-48D4-8A38-46A2EB089B74&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #a7bfde; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid #4f81bd 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;1998-06-01 00:00:00.000&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style='background: #2c4c74; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  none; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:white; font-family:Courier New; font-size:8pt'&gt;4&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #edf2f8; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #4f81bd 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;Accessories&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #edf2f8; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #4f81bd 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;2BE3BE36-D9A2-4EEE-B593-ED895D97C2A6&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #edf2f8; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #4f81bd 0.5pt; border-right:  solid #4f81bd 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;1998-06-01 00:00:00.000&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;&lt;br/&gt;To get the comma delimited list of Categories, we can use the COALESCE function and a string variable:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:9pt'&gt;&lt;span style='color:blue'&gt;DECLARE&lt;/span&gt; @categories &lt;span style='color:blue'&gt;varchar&lt;/span&gt;&lt;span style='color:gray'&gt;(&lt;/span&gt;200&lt;span style='color:gray'&gt;)&lt;br/&gt;&lt;/span&gt;&lt;span style='color:blue'&gt;SET&lt;/span&gt; @categories &lt;span style='color:gray'&gt;=&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:gray'&gt;NULL&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style='color:blue'&gt;SELECT&lt;/span&gt; @categories &lt;span style='color:gray'&gt;=&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:fuchsia'&gt;COALESCE&lt;/span&gt;&lt;span style='color:gray'&gt;(&lt;/span&gt;@categories &lt;span style='color:gray'&gt;+&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:red'&gt;','&lt;/span&gt;&lt;span style='color:gray'&gt;,&lt;/span&gt;&lt;span style='color:red'&gt;''&lt;/span&gt;&lt;span style='color:gray'&gt;)&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:gray'&gt;+&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;Name&lt;br/&gt;FROM&lt;/span&gt; Production&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductCategory&lt;br/&gt;&lt;br/&gt;&lt;span style='color:blue'&gt;SELECT&lt;/span&gt; @categories&lt;br/&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;And returns, as expected a string "Accessories,Bikes,Clothing,Components"&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;But now, how would we return the recordset of categories with a second column containing the list of subcategories.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I can get the list of subcategories for a single category but not for each category using the COALESCE method.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This is where recursive queries help. First I need to number each subcategory within the category. I can do that using RANK and ROW_NUMBER functions.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-size:9pt'&gt;&lt;span style='color:blue; font-family:Courier New'&gt;SELECT&lt;/span&gt;&lt;span style='font-family:Courier New'&gt;&lt;br /&gt;						&lt;br/&gt;    c&lt;span style='color:gray'&gt;.&lt;/span&gt;Name &lt;span style='color:blue'&gt;as&lt;/span&gt; Category&lt;span style='color:gray'&gt;,&lt;/span&gt;&lt;br /&gt;						&lt;br/&gt;    s&lt;span style='color:gray'&gt;.&lt;/span&gt;Name &lt;span style='color:blue'&gt;as&lt;/span&gt; SubCategory&lt;span style='color:gray'&gt;,&lt;br/&gt;&lt;/span&gt;&lt;br /&gt;						&lt;span style='color:fuchsia'&gt;ROW_NUMBER&lt;/span&gt;&lt;span style='color:gray'&gt;()&lt;/span&gt;&lt;br /&gt;						&lt;span style='color:blue'&gt;OVER&lt;/span&gt;&lt;span style='color:gray'&gt;(&lt;/span&gt;&lt;span style='color:blue'&gt;ORDER&lt;/span&gt;&lt;br /&gt;						&lt;span style='color:blue'&gt;BY&lt;/span&gt; c&lt;span style='color:gray'&gt;.&lt;/span&gt;Name&lt;span style='color:gray'&gt;,&lt;/span&gt;s&lt;span style='color:gray'&gt;.&lt;/span&gt;Name&lt;span style='color:gray'&gt;)&lt;/span&gt;&lt;br /&gt;						&lt;span style='color:gray'&gt;+&lt;/span&gt; 1 &lt;br/&gt;        &lt;span style='color:gray'&gt;-&lt;/span&gt;&lt;br /&gt;						&lt;span style='color:fuchsia'&gt;RANK&lt;/span&gt;&lt;span style='color:gray'&gt;()&lt;/span&gt;&lt;br /&gt;						&lt;span style='color:blue'&gt;OVER&lt;/span&gt;&lt;span style='color:gray'&gt;(&lt;/span&gt;&lt;span style='color:blue'&gt;ORDER&lt;/span&gt;&lt;br /&gt;						&lt;span style='color:blue'&gt;BY&lt;/span&gt; c&lt;span style='color:gray'&gt;.&lt;/span&gt;Name&lt;span style='color:gray'&gt;)&lt;/span&gt;&lt;br /&gt;						&lt;span style='color:blue'&gt;as&lt;/span&gt; SubCategoryNumber&lt;br/&gt;&lt;span style='color:blue'&gt;FROM&lt;/span&gt; Production&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductCategory c&lt;br/&gt;&lt;span style='color:gray'&gt;JOIN&lt;/span&gt; Production&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductSubCategory s&lt;br/&gt;&lt;span style='color:blue'&gt;ON&lt;/span&gt; c&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductCategoryID &lt;span style='color:gray'&gt;=&lt;/span&gt; s&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductCategoryID&lt;br/&gt;&lt;/span&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;And now the recursive query where each loop of the query adds to the comma delimited string with the initial value equal to the first subcategory&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;span style='font-family:Courier New; font-size:9pt'&gt;&lt;span style='color:blue'&gt;WITH&lt;/span&gt;&lt;br /&gt;					&lt;br/&gt;&lt;br/&gt;SubCategories&lt;span style='color:gray'&gt;(&lt;/span&gt;Category&lt;span style='color:gray'&gt;,&lt;/span&gt; Subcategory&lt;span style='color:gray'&gt;,&lt;/span&gt; SubCategoryNumber&lt;span style='color:gray'&gt;)&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;AS&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:gray'&gt;(&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;    &lt;span style='color:blue'&gt;SELECT&lt;/span&gt;&lt;br /&gt;					&lt;br/&gt;        c&lt;span style='color:gray'&gt;.&lt;/span&gt;Name &lt;span style='color:blue'&gt;as&lt;/span&gt; Category&lt;span style='color:gray'&gt;,&lt;/span&gt;&lt;br /&gt;					&lt;br/&gt;        s&lt;span style='color:gray'&gt;.&lt;/span&gt;Name &lt;span style='color:blue'&gt;as&lt;/span&gt; SubCategory&lt;span style='color:gray'&gt;,&lt;br/&gt;&lt;/span&gt;        &lt;span style='color:fuchsia'&gt;ROW_NUMBER&lt;/span&gt;&lt;span style='color:gray'&gt;()&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;OVER&lt;/span&gt;&lt;span style='color:gray'&gt;(&lt;/span&gt;&lt;span style='color:blue'&gt;ORDER&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;BY&lt;/span&gt; c&lt;span style='color:gray'&gt;.&lt;/span&gt;Name&lt;span style='color:gray'&gt;,&lt;/span&gt;s&lt;span style='color:gray'&gt;.&lt;/span&gt;Name&lt;span style='color:gray'&gt;)&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:gray'&gt;+&lt;/span&gt; 1 &lt;br/&gt;            &lt;span style='color:gray'&gt;-&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:fuchsia'&gt;RANK&lt;/span&gt;&lt;span style='color:gray'&gt;()&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;OVER&lt;/span&gt;&lt;span style='color:gray'&gt;(&lt;/span&gt;&lt;span style='color:blue'&gt;ORDER&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;BY&lt;/span&gt; c&lt;span style='color:gray'&gt;.&lt;/span&gt;Name&lt;span style='color:gray'&gt;)&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;as&lt;/span&gt; SubCategoryNumber&lt;br/&gt;    &lt;span style='color:blue'&gt;FROM&lt;/span&gt; Production&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductCategory c&lt;br/&gt;    &lt;span style='color:gray'&gt;JOIN&lt;/span&gt; Production&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductSubCategory s&lt;br/&gt;    &lt;span style='color:blue'&gt;ON&lt;/span&gt; c&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductCategoryID &lt;span style='color:gray'&gt;=&lt;/span&gt; s&lt;span style='color:gray'&gt;.&lt;/span&gt;ProductCategoryID &lt;span style='color:gray'&gt;),&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;TempCategories&lt;span style='color:gray'&gt;(&lt;/span&gt;Category&lt;span style='color:gray'&gt;,&lt;/span&gt; Subcategories&lt;span style='color:gray'&gt;,&lt;/span&gt; SubCategoryNumber&lt;span style='color:gray'&gt;)&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;AS&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:gray'&gt;(&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;    &lt;span style='color:blue'&gt;SELECT&lt;/span&gt; Category&lt;span style='color:gray'&gt;,&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:fuchsia'&gt;CAST&lt;/span&gt;&lt;span style='color:gray'&gt;(&lt;/span&gt;Subcategory &lt;span style='color:blue'&gt;as&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;varchar&lt;/span&gt;&lt;span style='color:gray'&gt;(&lt;/span&gt;&lt;span style='color:fuchsia'&gt;max&lt;/span&gt;&lt;span style='color:gray'&gt;)),&lt;/span&gt; SubCategoryNumber&lt;br/&gt;    &lt;span style='color:blue'&gt;FROM&lt;/span&gt; SubCategories&lt;br/&gt;    &lt;span style='color:blue'&gt;WHERE&lt;/span&gt; SubCategoryNumber &lt;span style='color:gray'&gt;=&lt;/span&gt; 1&lt;br/&gt;&lt;br/&gt;    &lt;span style='color:blue'&gt;UNION ALL&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;    &lt;span style='color:blue'&gt;SELECT&lt;/span&gt; TempCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;Category&lt;span style='color:gray'&gt;,&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:fuchsia'&gt;CAST&lt;/span&gt;&lt;span style='color:gray'&gt;(&lt;/span&gt;TempCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;SubCategories &lt;span style='color:gray'&gt;+&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:red'&gt;','&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:gray'&gt;+&lt;/span&gt; SubCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;Subcategory &lt;span style='color:blue'&gt;as&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;varchar&lt;/span&gt;&lt;span style='color:gray'&gt;(&lt;/span&gt;&lt;span style='color:fuchsia'&gt;max&lt;/span&gt;&lt;span style='color:gray'&gt;)),&lt;/span&gt; TempCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;SubCategoryNumber &lt;span style='color:gray'&gt;+&lt;/span&gt; 1&lt;br/&gt;    &lt;span style='color:blue'&gt;FROM&lt;/span&gt; TempCategories&lt;br/&gt;    &lt;span style='color:gray'&gt;JOIN&lt;/span&gt; SubCategories&lt;br/&gt;    &lt;span style='color:blue'&gt;ON&lt;/span&gt; TempCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;Category &lt;span style='color:gray'&gt;=&lt;/span&gt; SubCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;Category &lt;span style='color:gray'&gt;and&lt;/span&gt; TempCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;SubCategoryNumber &lt;span style='color:gray'&gt;+&lt;/span&gt; 1 &lt;span style='color:gray'&gt;=&lt;/span&gt; SubCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;SubCategoryNumber &lt;span style='color:gray'&gt;),&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;MaxCategories&lt;span style='color:gray'&gt;(&lt;/span&gt;Category&lt;span style='color:gray'&gt;,&lt;/span&gt; SubCategoryNumber&lt;span style='color:gray'&gt;)&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;AS&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:gray'&gt;(&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;    &lt;span style='color:blue'&gt;SELECT&lt;/span&gt; Category&lt;span style='color:gray'&gt;,&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:fuchsia'&gt;MAX&lt;/span&gt;&lt;span style='color:gray'&gt;(&lt;/span&gt;SubCategoryNumber&lt;span style='color:gray'&gt;)&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;AS&lt;/span&gt; SubCategoryNumber&lt;br/&gt;    &lt;span style='color:blue'&gt;FROM&lt;/span&gt; SubCategories&lt;br/&gt;    &lt;span style='color:blue'&gt;GROUP&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;BY&lt;/span&gt; Category &lt;span style='color:gray'&gt;),&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;Categories &lt;span style='color:gray'&gt;(&lt;/span&gt;Category&lt;span style='color:gray'&gt;,&lt;/span&gt; Subcategories&lt;span style='color:gray'&gt;)&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;AS&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:gray'&gt;(&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;    &lt;span style='color:blue'&gt;SELECT&lt;/span&gt; TempCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;Category&lt;span style='color:gray'&gt;,&lt;/span&gt; TempCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;Subcategories&lt;br/&gt;    &lt;span style='color:blue'&gt;FROM&lt;/span&gt; TempCategories&lt;br/&gt;    &lt;span style='color:gray'&gt;JOIN&lt;/span&gt; MaxCategories&lt;br/&gt;    &lt;span style='color:blue'&gt;ON&lt;/span&gt; TempCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;Category &lt;span style='color:gray'&gt;=&lt;/span&gt; MaxCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;Category &lt;span style='color:gray'&gt;AND&lt;/span&gt; TempCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;SubCategoryNumber &lt;span style='color:gray'&gt;=&lt;/span&gt; MaxCategories&lt;span style='color:gray'&gt;.&lt;/span&gt;SubCategoryNumber &lt;span style='color:gray'&gt;)&lt;br/&gt;&lt;br/&gt;&lt;/span&gt;&lt;span style='color:blue'&gt;SELECT&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:gray'&gt;*&lt;/span&gt;&lt;br /&gt;					&lt;span style='color:blue'&gt;FROM&lt;/span&gt; Categories&lt;br/&gt;&lt;br /&gt;				&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Which returns:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;div&gt;&lt;table border='0' style='border-collapse:collapse'&gt;&lt;colgroup&gt;&lt;col style='width:118px'/&gt;&lt;col style='width:520px'/&gt;&lt;/colgroup&gt;&lt;tbody valign='top'&gt;&lt;tr style='background: white'&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #c0504d 3.0pt; border-right:  none'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;&lt;strong&gt;Category&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #c0504d 3.0pt; border-right:  none'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;&lt;strong&gt;Subcategories&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style='background: #2c4c74; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #2c4c74 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:white; font-family:Courier New; font-size:8pt'&gt;Components&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #a7bfde; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid #4f81bd 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;Bottom Brackets,Brakes,Chains,Cranksets,Derailleurs,Forks,Handlebars,Headsets,Mountain Frames,Pedals,Road Frames,Saddles,Touring Frames,Wheels&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style='background: #2c4c74; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #2c4c74 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:white; font-family:Courier New; font-size:8pt'&gt;Clothing&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #edf2f8; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid #4f81bd 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;Bib-Shorts,Caps,Gloves,Jerseys,Shorts,Socks,Tights,Vests&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style='background: #2c4c74; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #2c4c74 0.5pt; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:white; font-family:Courier New; font-size:8pt'&gt;Bikes&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #a7bfde; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid white 0.5pt; border-right:  solid #4f81bd 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;Mountain Bikes,Road Bikes,Touring Bikes&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style='background: #2c4c74; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  none; border-right:  solid white 0.5pt'&gt;&lt;p&gt;&lt;span style='color:white; font-family:Courier New; font-size:8pt'&gt;Accessories&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td style='background: #edf2f8; padding-left: 7px; padding-right: 7px; border-top:  none; border-left:  none; border-bottom:  solid #4f81bd 0.5pt; border-right:  solid #4f81bd 0.5pt'&gt;&lt;p&gt;&lt;span style='color:black; font-family:Courier New; font-size:8pt'&gt;Bike Racks,Bike Stands,Bottles and Cages,Cleaners,Fenders,Helmets,Hydration Packs,Lights,Locks,Panniers,Pumps,Tires and Tubes&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;If we look at each query:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;&lt;strong&gt;SubCategories&lt;/strong&gt;, we've seen already, returns the full list of categories and subcategories with a subcategory number, string at 1, for each category.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;TempCategories&lt;/strong&gt; is the recursive query and adds at each level the previous subcategory list with the current subcategory, so the first subcategory contains itself, the second catains the first and itself, the third contains the first, the second and itself and so on. We then need to only keep the last record of each category that contains every subcategory.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;MaxCategories&lt;/strong&gt; contains the highest  SubcategoryNumber for each category.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Categories&lt;/strong&gt; joins TempCategories and MaxCategory to only retain the highest subcategory number per category. The result we need.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;p&gt;The aggregation operation defined in TempCategories (here adding the string together) could be replaced with any custom aggregation. It iteratively, in a known sequence, combines the previous calculated value with the new value for that row.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt; &lt;/p&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6259562913746865237-4134453226310325991?l=blog.mridey.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/MRidey-Blog/~4/d6Y5ozfkSFg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/MRidey-Blog/~3/d6Y5ozfkSFg/string-and-custom-aggregations-using.html</link><author>noreply@blogger.com (Marc Ridey)</author><thr:total>1</thr:total><feedburner:origLink>http://blog.mridey.com/2009/05/string-and-custom-aggregations-using.html</feedburner:origLink></item></channel></rss>

