Inheritance: System.EventArgs
    /// <summary>
    /// Makes a request against RSS Weather service and add update the layer's table
    /// </summary>
    /// <param name="zipCode"></param>
    /// <param name="Lat"></param>
    /// <param name="Lon"></param>
		private void AddWeatherItem(long zipCode, double Lat, double Lon)
		{
			try
			{	
				string cityName;
				double lat, lon;
				int temp;
				string condition;
				string desc;
				string iconPath;
				string day;
				string date;
				int low;
				int high;
				int iconCode;
				int iconWidth = 52; //default values
				int iconHeight = 52;
				Bitmap bitmap = null;

				DataRow dbr = m_table.Rows.Find(zipCode);
				if (dbr != null)
				{
					// get the date 
					DateTime updateDate = Convert.ToDateTime(dbr[14]);
					TimeSpan ts = DateTime.Now - updateDate;
					
					// if the item had been updated in the past 15 minutes, simply bail out.
					if (ts.TotalMinutes < 15)
						return;
				}

        //the base URL for the service
				string url = "http://xml.weather.yahoo.com/forecastrss?p=";
        //the RegEx used to extract the icon path from the HTML tag
				string regxQry = "(http://(\\\")?(.*?\\.gif))";
				XmlTextReader reader = null;
				XmlDocument doc;
				XmlNode node;
				
				try
				{
          //make the request and get the result back into XmlReader
					reader = new XmlTextReader(url + zipCode.ToString());
				}
				catch(Exception ex)
				{
					System.Diagnostics.Trace.WriteLine(ex.Message);
					return;
				}

        //load the XmlReader to an xml doc
				doc = new XmlDocument();
				doc.Load(reader);

        //set an XmlNamespaceManager since we have to make explicit namespace searches
        XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(doc.NameTable);
				//Add the namespaces used in the xml doc to the XmlNamespaceManager.
				xmlnsManager.AddNamespace("yweather", "http://xml.weather.yahoo.com/ns/rss/1.0");
				xmlnsManager.AddNamespace("geo", "http://www.w3.org/2003/01/geo/wgs84_pos#");

        //make sure that the node exists
				node = doc.DocumentElement.SelectSingleNode("/rss/channel/yweather:location/@city", xmlnsManager);
				if(null == node)
					return;

        //get the cityname
				cityName = doc.DocumentElement.SelectSingleNode("/rss/channel/yweather:location/@city", xmlnsManager).InnerXml;
				if(Lat == 0.0 && Lon == 0.0)
				{
          //in case that the caller did not specify a coordinate, get the default coordinate from the service
					lat = Convert.ToDouble(doc.DocumentElement.SelectSingleNode("/rss/channel/item/geo:lat", xmlnsManager).InnerXml);
					lon = Convert.ToDouble(doc.DocumentElement.SelectSingleNode("/rss/channel/item/geo:long", xmlnsManager).InnerXml);
				}
				else
				{
					lat = Lat;
					lon = Lon;
				}

        //extract the rest of the information from the RSS response
				condition = doc.DocumentElement.SelectSingleNode("/rss/channel/item/yweather:condition/@text", xmlnsManager).InnerXml;
				iconCode = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("/rss/channel/item/yweather:condition/@code", xmlnsManager).InnerXml);
				temp = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("/rss/channel/item/yweather:condition/@temp", xmlnsManager).InnerXml);
				desc = doc.DocumentElement.SelectSingleNode("/rss/channel/item/description").InnerXml;
				day = doc.DocumentElement.SelectSingleNode("/rss/channel/item/yweather:forecast/@day", xmlnsManager).InnerXml;
				date = doc.DocumentElement.SelectSingleNode("/rss/channel/item/yweather:forecast/@date", xmlnsManager).InnerXml;
				low = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("/rss/channel/item/yweather:forecast/@low", xmlnsManager).InnerXml);
				high = Convert.ToInt32(doc.DocumentElement.SelectSingleNode("/rss/channel/item/yweather:forecast/@high", xmlnsManager).InnerXml);


				//use regex in order to extract the icon name from the html script
				Match m = Regex.Match(desc,regxQry);
				if(m.Success)
				{
					iconPath = m.Value;

					//add the icon ID to the symbology table
					DataRow tr = m_symbolTable.Rows.Find(iconCode);
					if(null == tr)
					{
						//get the icon from the website
						bitmap = DownloadIcon(iconPath, out iconWidth, out iconHeight);

            //create a new record
						tr = m_symbolTable.NewRow();
						tr[1] = iconCode;
						tr[3] = iconWidth;
						tr[4] = iconHeight;
						tr[6] = bitmap;
            
            //update the symbol table. The initialization of the symbol cannot take place in here, since
            //this code gets executed on a background thread.
						lock(m_symbolTable)
						{
							m_symbolTable.Rows.Add(tr);
						}
					}
					else //get the icon's dimensions from the table
					{
						//get the icon's dimensions from the table
						iconWidth = Convert.ToInt32(tr[3]);
						iconHeight = Convert.ToInt32(tr[4]);
					}
				}
				else
				{
					iconPath = "";
				}

        //test whether the record already exists in the layer's table.
				if(null == dbr) //in case that the record does not exist
				{
          //create a new record
					dbr = m_table.NewRow();

          if (!m_table.Columns[0].AutoIncrement)
            dbr[0] = Convert.ToInt32(DateTime.Now.Millisecond);

					//add the item to the table
					lock (m_table)
					{
						dbr[1] = zipCode;
						dbr[2] = cityName;
						dbr[3] = lat;
						dbr[4] = lon;
						dbr[5] = temp;
						dbr[6] = condition;
						dbr[7] = iconPath;
						dbr[8] = iconCode;
						dbr[9] = day;
						dbr[10] = date;
						dbr[11] = low;
						dbr[12] = high;
						dbr[13] = false;
						dbr[14] = DateTime.Now;
					
						m_table.Rows.Add(dbr);
					}
				}
				else //in case that the record exists, just update it
				{
					//update the record
					lock (m_table)
					{
						dbr[5] = temp;
						dbr[6] = condition;
						dbr[7] = iconPath;
						dbr[8] = iconCode;
						dbr[9] = day;
						dbr[10] = date;
						dbr[11] = low;
						dbr[12] = high;
						dbr[14] = DateTime.Now;

						dbr.AcceptChanges();
					}
				}

				base.m_bIsCompiledDirty = true;

				//fire an event to notify the user that the item has been updated
        if (OnWeatherItemAdded != null)
        {
          WeatherItemEventArgs weatherItemEventArgs = new WeatherItemEventArgs(Convert.ToInt32(dbr[0]), zipCode, lon, lat, iconWidth, iconHeight);
          OnWeatherItemAdded(this, weatherItemEventArgs);
        }

			}
			catch(Exception ex)
			{
				System.Diagnostics.Trace.WriteLine("AddWeatherItem: " + ex.Message);
			}
		}
      private void RefreshWeatherItemInvoked(WeatherItemEventArgs weatherItemInfo)
      {
        ITransformation transform = m_activeView.ScreenDisplay.DisplayTransformation as ITransformation;
        if (transform == null)
          return;

        double[] iconDimensions = new double[2];
        iconDimensions[0] = (double)weatherItemInfo.IconWidth; 
        iconDimensions[1] = (double)weatherItemInfo.IconHeight;

        double[] iconDimensionsMap = new double[2];

        transform.TransformMeasuresFF(esriTransformDirection.esriTransformReverse, 1, ref iconDimensionsMap[0], ref iconDimensions[0]);

        m_invalidateExtent.PutCoords(0, 0, iconDimensionsMap[0], iconDimensionsMap[0]);
        m_point.PutCoords(weatherItemInfo.mapX, weatherItemInfo.mapY);
        m_invalidateExtent.CenterAt(m_point);

        m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeography, m_weatherLayer, m_invalidateExtent);
        m_activeView.ScreenDisplay.UpdateWindow();
      }
    /// <summary>
    /// weather layer ItemAdded event handler
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    /// <remarks>gets fired when an item is added to the table</remarks>
		private void OnWeatherItemAdded(object sender, WeatherItemEventArgs args)
		{
			// use the invoke helper since this event gets fired on a different thread
      m_invokeHelper.RefreshWeatherItem(args);
		}
 public void RefreshWeatherItem(WeatherItemEventArgs weatherItemInfo)
 {
   try
   {
     // Invoke the RefreshInternal through its delegate
     if (!this.IsDisposed && this.IsHandleCreated)
       Invoke(new RefreshWeatherItemHelper(RefreshWeatherItemInvoked), new object[] { weatherItemInfo });
   }
   catch (Exception ex)
   {
     System.Diagnostics.Trace.WriteLine(ex.Message);
   }
 }