Category Archives: c#

Modeless vs Modal Dialog

Simple explanation of the differences between modeless and modal dialogs.

win1 dialog

Show() – Modeless

  • Doesn’t stop executing.
  • Can show and create several windows and interact all at once.

ShowDialog() – Modal

  • Intercepts code execution.
  • Stops interaction with other windows.
  • Ideal for presenting the user with a choice that must be made before continuing.
  • When a form is closed the form object and all it’s control information still exists until the referencing variable goes out of scope:

Form1 myForm = new Form1();
myForm .ShowDialog();
....lots of code here.....
myForm.Dispose();

Advertisements

Use a Dictionary to store results from a DataReader

Quick way to get a DataReader result into a Dictionary:


while (dr.Read())
{

Dictionary<string, object> surveyDict = new Dictionary<string, object>();

aDict = Enumerable.Range(0, dr.FieldCount).ToDictionary(dr.GetName, dr.GetValue);

}


 

 

Convert Latitude Longitude to Easting Northings

Take a look and hopefully it works in your code.


private double toRad(double val)
{
	return val * (Math.PI / 180);
}
        
public void LatLongToEastNorth(double latitude, double longitude)
{
       //This will not work unless you have your lats and longs in decimal degrees.
       latitude = toRad(latitude);
       longitude = toRad(longitude);

       double a = 6377563.396, b = 6356256.910; // Airy 1830 major &amp; minor semi-axes
       //double a = 6378137.0, b = 6356752.314245; WGS84 major &amp; minor semi-axes

       double F0 = 0.9996012717; // NatGrid scale factor on central meridian
       double lat0 = toRad(49);
       double lon0 = toRad(-2); // NatGrid true origin
       double N0 = -100000, E0 = 400000; // northing &amp; easting of true origin, metres
       double e2 = 1 - (b * b) / (a * a); // eccentricity squared
       double n = (a - b) / (a + b), n2 = n * n, n3 = n * n * n;

       double cosLat = Math.Cos(latitude), sinLat = Math.Sin(latitude);
       double nu = a * F0 / Math.Sqrt(1 - e2 * sinLat * sinLat) ; // transverse radius of curvature
       double rho = a * F0 * (1 - e2) / Math.Pow(1 - e2 * sinLat * sinLat, 1.5); // meridional radius of curvature
   
       double eta2 = nu / rho - 1;

       double Ma = (1 + n + (5 / 4) * n2 + (5 / 4) * n3) * (latitude - lat0);
       double Mb = (3 * n + 3 * n * n + (21/8)*n3) * Math.Sin(latitude - lat0) * Math.Cos(latitude + lat0);
       double Mc = ((15/8)*n2 + (15/8)*n3) * Math.Sin(2 * (latitude - lat0)) * Math.Cos(2 * (latitude + lat0));
       double Md = (35 / 24) * n3 * Math.Sin(3 * (latitude - lat0)) * Math.Cos(3 * (latitude + lat0));
       double M = b * F0 * (Ma - Mb + Mc - Md); // meridional arc

       double cos3lat = cosLat * cosLat * cosLat;
       double cos5lat = cos3lat * cosLat * cosLat;
       double tan2lat = Math.Tan(latitude) * Math.Tan(latitude);
       double tan4lat = tan2lat * tan2lat;

       double I = M + N0;
       double II = (nu / 2) * sinLat * cosLat;
       double III = (nu / 24) * sinLat * cos3lat * (5 - tan2lat + 9 * eta2);
       double IIIA = (nu / 720) * sinLat * cos5lat * (61 - 58 * tan2lat + tan4lat);
       double IV = nu * cosLat;
       double V = (nu / 6) * cos3lat * (nu / rho - tan2lat);
       double VI = (nu / 120) * cos5lat * (5 - 18 * tan2lat + tan4lat + 14 * eta2 - 58 * tan2lat * eta2);

       double dLon = longitude - lon0;
       double dLon2 = dLon * dLon, dLon3 = dLon2 * dLon, dLon4 = dLon3 * dLon, dLon5 = dLon4 * dLon, dLon6 = dLon5 * dLon;

       double N = I + II * dLon2 + III * dLon4 + IIIA * dLon6; //This is the northing
       double E = E0 + IV * dLon + V * dLon3 + VI * dLon5; //This is the easting  
}

How to query ArcIMS services with ArcObjects

IIMSServiceDescription imsServiceDescription = new IMSServiceNameClass();
imsServiceDescription.URL = @"you server here";                 
imsServiceDescription.Name = "catalog";

IIMSAxlRequest axlRequest = (IIMSAxlRequest)imsServiceDescription;
String result = axlRequest.SendAxlRequest("<GETCLIENTSERVICES/>", false, null, false, true);

IXmlPropertySet2 xmlProps = new XmlPropertySetClass();
xmlProps.SetXml(result);
object val = new object();
xmlProps.GetAttribute("RESPONSE/SERVICES/SERVICE", "NAME", out val);

object[] vals = (object[]) val;

for (int i = 0; i &lt; vals.Length; i++)
{
     Debug.WriteLine(vals[i].ToString());
}

How to Show Click Once version in form title text

I think it’s handy to show the version of your software sometimes in the title text of your form to make sure you can see at a glance that the click once distro is the same as the program that is currently running on a PC. In order to achieve this do the following:

Make sure add a reference in your project to System.Deployment as well as the including the using statement.  You need this in order to access some specific libraries in this assembley.

In your initialisation of your form you should check to see that the version running has been deployed by Click Once.  This means that debug versions of this won’t work but live deployed versions will – if you don’t do this you will get an exception.

See code below:

           if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
            {
                    this.Text = String.Format("My Foo Program {0}",
                    System.Deployment.Application.ApplicationDeployment.CurrentDeployment.CurrentVersion);
            }

Issues with persisting changes to the scale in PageLayout (LayoutView) using ArcObjects

Scenario

Now and again you may find yourself developing an application outside of ArcMap i.e. essentially an ArcEngine app.

I was developing an application that accessed an mxd via the IMapDocument interface and tried to persist a change in the map scale in the Layout View.  Every time I changed the scale and saved the mxd – however the original scale would not change and the programmatic new scale was ignored!

This was very frustrating indeed, I was sure that there must be a way to persist this change as it’s not exactly NASA missile launch code – I’m just trying to change a scale damn it!

ArcMap Scale

Highlight of the scale control in the layoutview of ArcMap

Solution

Anyway, it so happens that there is a fix, but it’s kind of unusual and not exactly intuitive or obvious to the developer coming at this problem cold.

Firstly we have to make use of some win32 API calls and most importantly to call IActiveView.Activate and pass our call to GetDesktopWindow().  This does the trick and is absolutely essential if you want to get this kind of change persisted.  Take a look at the code below to see how it’s done:

  
[DllImport("User32.dll")]
public static extern int GetDesktopWindow();

private void ChangeMyScale()
{
    IMapDocument MapDoc;
    mapDoc = new MapDocumentClass();
    mapDoc.Open(@"C:\Foo\Bar.mxd",null);
    IPageLayout pageLayout = mapDoc.PageLayout;
    IActiveView activeView = (IActiveView)pageLayout;
    activeView = (IActiveView) mapDoc.PageLayout;
    activeView.Activate(GetDesktopWindow()); //Key line!!
    mapDoc.ActiveView.FocusMap.MapScale = 10000; //Now we can change the scale!!
    activeView.Refresh();

    MessageBox.Show(@"We have an mxd called:" + mapDoc.DocumentFilename +
    "\nExtent: 1 to " + mapDoc.ActiveView.FocusMap.MapScale);

    mapDoc.Save(true, false)
    mapDoc.Close();
}

Other things to bear in mind, code such as:

MapDoc.SetActiveView((IActiveView)pageLayout)

only sets the view for the application as PageLayout, in order to get control of the specified window you have to use the Activate method:

<pre>activeView.Activate(GetDesktopWindow())

When working with the IActiveView interface on a MapDocument object, you should always first call IActiveView::Activate() in order to properly initialize the display of the PageLayout or Map object.

The MxDocument, MapServer objects, MapControl and PageLayoutControl all initialise display objects automatically after opening an MXD, but MapDocument DOES NOT DO THIS, so you should call Activate() before working with any other members of IActiveView.

So to summarise, if your application has a user interface, you should call Activate() with the hWnd of the application’s client area.  If your application runs in the background and has no windows, you retrieve a valid hWnd from the GDI GetDesktopWindow() function, part of the Win32 API.

Conclusion

I am hopeful that ESRI will change this so that you don’t have to, what I view totally unnecessary calls to the Windows API etc.  Maybe it will be fixed properly in version 10 or some other update to that, but I wouldn’t hold your breath!

Anyway I hope it’s useful to you and stops you burning lots of valuable dev time!