Thursday, 8 December 2011

Custom Action Handlers forArcFM GDB Manager

You can create your own custom Action Handlers for Geodatabase manager.
Geodatabase Manger works with action handlers. These action handlers are nothing but a set of executions which are set to happen at certain events. GDB Manager also comes with  ActionHandlers but our business requirement may trouble us to write one.

The following steps may help you create and implement one.

STEP 1: Code a custom action handlers Impletement PXActionHandler for your class
STEP 2: To make your desired functionality happen OVERRIDE the ENBALED and SUBEXECUTE            
              methods based on your requirement
STEP 3: Once you are done with coding part, create a STRONG NAME KEY for your assembly
STEP 4: Copy your assembly to Program Files\Miner and Miner\ArcFM Solution\bin
STEP 5: Open your VS CMD prompt and CD to Program Files\Miner and Miner\ArcFM Solution\bin and
              generate a public key token and make a note of it. Use sn.exe to create one.
STEP 6: In windows explorer find GeodatabaseManagerAdmin.exe.config file in Program Files\Miner and
               Miner\ArcFM Solution\bin folder and edit it in NOTEPAD. Find <ActionHandlerAssemblies> tag
               and add your custom action handler assembly in there as in the same format of other
               ActionHandlers with TYPE, PUBLIC KEY TOKEN, VERSION etc
STEP 7: Save and close the config file, Now open you GDB manager tool -> under Version Processing tab
               under any PROCESS right click and add NEW ACTION HANDLER and select your custom
               ActionHandler on the dropdown at your right hand side.



happy reconciling,

ArcFM Snippet #4 - Enabling & Disabling an Autoupdater


Use IMMAutoUpdater interface to disable any autoupdater

IMMAutoUpdater autoUpdater =Use "TYPE" to get your Autoupdater.

autoUpdater.AutoUpdaterMode=mmAutoUpdaterMode.mmAUMNoEvents;

To Rollback the Autoupdater or to set the autoupdater back in place, you save the autoupdater mode before setting it to NOEvents. Later that can be used to reset your AU anytime.

cheers,
Happy coding

C# 4 ! ! !

Just started with C # 4 and Visual Studio2010. Lots of updates and enhancements both in VS and C#, loooooong way to go

Saturday, 3 December 2011

Cursors in ArcObjects, Explained


In ArcObjects, a cursor refers to a set of records or subset of records obtained by any query (Attribute/ Spatial) over a FeatureClass or Table. -> Getting confused with selection set and Cursors? Cursors are always not for display, whereas selection set is bound by display or any selected features in ArcMap display is called as selection set.

Cursor ? FeatureCursor = ?
Cursor and FeatureCursor are similar objects. The work location of them brought in separation or two different terminologies among them. Yes, Cursors work location is always a table, whereas FeatureCursor’s work location is always a FeatureClass or IFeatureClass. A Cursor would return you any object that you have queried for whereas IFeatureCursor would return you an IFeature.

Types of Cursors
There are three types of cursors found in both the Cursor and FeatureCursor classes. The most commonly used type of cursor is the Search Cursor. It is used in query operations to return a subset of records based on your query. Search Cursors are read-only cursors.  Insert, update or delete is not possible with a Search Cursor.
A second type of cursor, the Insert Cursor, is specifically used to insert a new record in a table. The Update Cursor is used to update or delete records in a table. The records returned in an Update or Search Cursor can be constrained to match attribute criteria and/or spatial criteria. It is important that you create the proper type of cursor for the operation that you are performing.

Cursor Class
The Cursor class is used to create objects that work with database tables. The Cursor class in ArcObjects is an instantiable class. Which means you must use another object to obtain an instance of this class. In this case, the Table class in ArcObjects is used to create an instance of the cursor class. The Table class contains three methods that can be used to return an instance of the Cursor class. The type of cursor returned is dependent upon the method called. Figure 1 shows the Object model diagram for the Table class in ArcObjects.


 The ITable interface has three methods that can be used to return specific types of cursor objects. The Search, Insert, and Update methods on ITable are used to return cursor instances. The names of the methods correspond to the type of cursor returned.
After one of these methods has been called, ArcObjects returns an instance of ICursor. Figure 2 shows the object model diagram for the Cursor class. Search, Insert, and Update all return an instance of ICursor. ICursor has one property (Fields) and a number of methods that can be used to manipulate the subset of records. Some of the methods available on ICursor may not be applicable depending on the type of cursor that you are working with. For instance, if you created a Search Cursor, the InsertRow and UpdateRow methods will return an error if called since you are not working with Insert or Update Cursors.


FeatureCursor Class
The FeatureCursor class is very similar to the Cursor class with the exception that FeatureCursor are used when you’re working with geographic datasets rather than traditional database tables. Geographic datasets are typically shapefiles and geodatabase FeatureClass. Similar to the Cursor class, the FeatureCursor class is an instantiable class created through the use of a method on a FeatureClass object. We also have Search, Insert and Update methods alike ITable interface which returns an instance of IFeatureCursor. The properties and methods available on IFeatureCursor are functionally similar to those on ICursor.


Applying Attribute and Spatial Constraints
While you browse along the OMD of a FeatureClass and Table, Search, Insert and Update methods are used to return a cursor that contains a parameter of IQueryFilter instance.
IQueryFilter object is the query to subset a table or it helps you to subset a record from a table or a FeatureClass, in memory. Similarly for any query of Spatial sort SpatialFilter should be used, but SpatialFilter can only be applied on a FeatureClass. If further attempt over the Table gives you an ERROR as because we lack spatial information over any normal table.
  
QueryFilter
To subset any record from a table or a FeatureClass, you need to define a QueryFilter which specifies the records to be returned. Create a new instance of IQueryFilter and define an attribute constraint for your search by using WhereClause property.

IQueryFilter qFilter = new QueryFilterClass;
qFilter.WhereClasue=”Name=’ArcObjects’”;

This would be used as like
 IFeatureCursor fCursor= featureClass.Search (qFilter, true);


SpatialFilter
As discussed earlier a SpatialFilter can only be applied to produce a subset of records based on spatial criteria.
Just like QueryFilter, SpatialFilter is also a creatable class so the New keyword can be used to create an instance of this class. SpatialFilter uses a Geometry property and a SpatialRel property to define the search criteria. The Geometry property is used to specify a particular geographic feature. SpatialRel can be set to one of a predefined set of constants such as intersects, overlaps, or touches. Because SpatialFilter is a type of QueryFilter, it also has access to all the methods and properties on that class. Therefore, you can use the WhereClause property on IQueryFilter to combine spatial and attribute constraints. The below snippet helps you understand how a SpatialFilter and QueryFilter can be combined together.

ISpatialFilter spatialFilter = new SpatialFilterClass;
spatialFilter.Geometry = pMyPloygon;
spatialFilter.SpatialRel = esriSpatialRelContains;
spatialFilter.WhereClause =”Name=’ArcObjects’”;
IFeatureCursor fCursor = featureClass.Search (spatialFilter, true);

Accessing Records in a Cursor
I believe we have a good understanding on creating cursors, now let’s look at how we can access the cursor (records) returned from a table or FeatureClass.
When a cursor is created you also get a Pointer created, this pointer points to the first record in the cursor while the cursor is initialized. To keep moving to the next record you need to make a call to the NextRow (Table) or NextFeature (IFeatureClass) method. These two methods help you to move the pointer ahead from its current position in the cursor and thereby fetching that particular record information. Subsequent call to the NextRow or NextFeature methods will keep the pointer heading towards the end of the record set or the Cursor which will return null at once point.

IFeatureCursor featureCursor= featureClass.Search (queryFilter, true);
IFeature pFeature=featureCursor.NextFeature ();
While (pFeature! =null)
{
                // To-do any of your logic

                // this keeps the pointer moving head of the current position
                PFeaure= featureCursor.NextFeature ();
}

Reference
Understanding Cursors in ArcObjects by Eric Pimpler, President, GeoSpatial Training & Consulting, LLC

Friday, 2 December 2011

Why do my BaseTool not hitting OnCreate? ? ?

I could find my BaseTool not hitting OnCreate Method many times. While I get into customize window I realize my constructor is been hit but then its not getting into OnCreate :(.
Also while I navigate to my category, again I find my Constructor is been hit but not OnCreate. All my intializations are within my OnCreate method by tradition. Whlie not gettin into OnCreate everytime am gettin my objects null hence,my tool says OBJECT NOT SET TO THE REFERENCE OF AN OBJECT, worried :'(.... any idea anyone? ?

Rajesh K

Saturday, 26 November 2011

Disabling Autoupdater @ runtime - - - > Possible?

oh, yea very well possible will share 2mrw, time to bed ;)

Quick helper to get IMMPxApplication reference


IMMPxIntegrationCache mmPxIntegrationCache =
                Application.FindExtensionByName("Session Manager Integration Extension") as IMMPxIntegrationCache;
            IMMPxApplication mmPxApplication = mmPxIntegrationCache .Application;


but have in mind, this gonna not work if you have WFM(workflow manager) in place :)

U got to use "Workflow Manager Integration" instead of "Session Manager Integration Extension"


Cheers,
happy coding...
would be sharing my findings always

GUIDs


IGraphicsLayer
"{34B2EF81-F4AC-11D1-A245-080009B6F22B}"

IDataLayer
"{6CA416B1-E160-11D2-9F4E-00C04F6BC78E}"

IAnnotationLayer
"{4AEDC069-B599-424B-A374-49602ABAD308}"

ICadLayer
"{E299ADBC-A5C3-11D2-9B10-00C04FA33299}"

ICompositeGraphicsLayer
"{9646BB82-9512-11D2-A2F6-080009B6F22B}"

ITopologyLayer
"{FB6337E3-610A-4BC2-9142-760D954C22EB}"

IRasterLayer
"{D02371C7-35F7-11D2-B1F2-00C04F8EDEFF}"

IGroupLayer
"{EDAD6644-1810-11D1-86AE-0000F8751720}"

IDimensionLayer
"{0737082E-958E-11D4-80ED-00C04F601565}"

IGeoFeatureLayer
"{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}"

IFeatureLayer
"{40A9E885-5533-11D0-98BE-00805F7CED21}"

ILayer
"{34C20002-4D3C-11D0-92D8-00805F7C28B0}"

IMapServerLayer
"{E9B56157-7EB7-4DB3-9958-AFBF3B5E1470}"

IMapServerSublayer
"{B059B902-5C7A-4287-982E-EF0BC77C6AAB}"

INetworkLayer
"{82870538-E09E-42C0-9228-CBCB244B91BA}"

IRasterCatalogLayer
"{AF9930F0-F61E-11D3-8D6C-00C04F5B87B2}"

ArcSDE Query to increase the BLOB size during "UNABLE TO SAVE STORED DISPLAY"

sdeconfig -o alter -v MAXBLOBSIZE=3000000 -i 5151 -s myserver -u sde -p sde

Thursday, 24 November 2011

"UNABLE TO SAVE STORED DISPLAY" - - - Quick Tip

Sometimes, our stored displays will not get saved, it prompts "UNABLE TO SAVE STORED DISPLAY."
A quick trick to solve this is to do Alt+F+A (save as) to your MXD and overrite your stored display. Most of the times this will help you. If not you got to increase your BLOB size. Will share the query soon, not in mind at present ;)

Cheers
Happy coding! ! !

Monday, 21 November 2011

Custom Symbology does not display after a particular zoom level - S O L V E D :)

IMap pMap= mxDocument.FocusMap;
IGraphicsContainer graphicContainer= pMap as IGraphicsContainer;

// QI FeatureLayer to IGeofeatureLayer-> renderer-> use the method to get symbology of any feature by
//passing your IFeature

IElement element= markerElement as IElement;
IGroupElement grpElement= new GroupElementClass();
grpElement.Add(element);

// QI the IGroupElement back to IEement after adding all your element to a IGroupElement.
// you can also loop the IEnumElement from IGroupElement to add individual element to the active view, but
// HERE COMES THE ISSUE OF NOT DISPLAYING THE SYMBOLOGY GRAPHICS
// BEYOND CERTAIN ZOOM SCALE. My case was 200 scale, I doubt this could be a ESRI bug!!!.

graphicContainer.Add(graphicContainer as IElement,0);

// Refesh your active view


Cheers
happy Coding


Monday, 7 November 2011

Change your cursor with ESRI Add-in Tool

I was fighting a bit to change my Add-In cursor to a wait cursor during execution process. First cycle goes smooth and from then on I could not find the change in the cursor. All I could realise is that the cursor is not gettin changed but in reality the cursor was getting changed to WAITCURSOR which was not reflecting in the screen.
The reason behind was Windows sends the window that contains the mouse cursor the WM_SETCURSOR message, giving it an opportunity to change the cursor shape. A control like TextBox takes advantage of that, changing the cursor into a I-bar. The Control.Cursor property determines what shape will be used.
The Current.Cursor property changes the shape directly, without waiting for a WM_SETCURSOR response. In most cases, that shape is unlikely to survive for long. As soon as the user moves the mouse, WM_SETCURSOR changes it back to Control.Cursor.
The UseWaitCursor property was added in .NET 2.0 to make it easier to display an hourglass. Unfortunately,
it doesn't work very well. It requires a WM_SETCURSOR message to change the shape and that won't happen when you set the property to true and then do something that takes a while.

 Use this class to set the cursor
public class UseWaitCursor : IDisposable
    {

        public UseWaitCursor()
        {
            Enabled = true;
        }
        #region IDisposable Members

        public void Dispose()
        {
            Enabled = false;
        }
        public static bool Enabled
        {
            get { return MyAddinTool._ myDocWindow.UseWaitCursor; }
            set
            {
           if (value.Equals(MyAddinTool._myDocWindow.UseWaitCursor)) return;
                MyAddinTool._ myDocWindow.UseWaitCursor = value;
                if (_myDocWindow.ActiveControl != null && MyAddinTool._ myDocWindow.ActiveControl.Handle != null)
                    SendMessage(MyAddinTool._ myDocWindow.ActiveControl.Handle, 0x20, MyAddinTool._ myDocWindow.ActiveControl.Handle, (IntPtr)1);
            }
        }

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr wp, IntPtr lp);
        #endregion
    }


using (new UseWaitCursor())
{
   //TODO all your code goes here or this ares says how long your curosr needs to
    be in WAITCUROSR style.
}
If required, use Finally block to change your cursor back to default Tool's cursor.



After Implementing the class above I was able to see my cursor change happening in the screen. Similar goes for Settin status message sometimes :)

Cheers
Happy coding

Thursday, 3 November 2011

Handle ESRI AddIn DockableWindow Close event

Friends,

I have really not used the close event of the Dockable window, instead I have used the OnUpdate method in to check the DockableWindow visibility to do necessary actions.
Snippet as below


protected override void OnUpdate()
{
     Enabled = ArcMap.Application != null;

     if (!_dockWindow.IsVisible() && !_toRollBack)
          RollBackActiveView()}

_toRollBack is a bool variable to avoid infinite loop during execution.

Do not forget to set the BOOL variable to false where ever you make the DockableWindow visible.

would be interested to understand few discussions? ? ?




Cheers Happy Coding :)

Friday, 28 October 2011

ArcFM Snippet #1 - To get Current Session ID and Current Session's Version


IMMPxApplication mmPxApplication = IApplication as IMMPxApplication;
IMMSessionManager2 ObjMSessionManager = mmPxApplication.FindPxExtensionByName
                    ("MMSessionManager") as IMMSessionManager2;

// If you this is a subtask you would get the node Id as a parameted in IMMPxSubtas.Execute Method.
int currentNodeId = currentNode.Id; bool blnBoolean = true;

// Acquiring the current session and session id
                ObjMSession = ObjMSessionManager.GetSession(ref intNodeId, ref blnBoolean);

//Getting the current session’s version
IMMPxApplicationEx2 ObjPxAppEx= IMMPxApplication as IMMPxApplicationEx2;
IMMPxSDEVersion ObjPxSDEVersion = ObjPxAppEx.GetSDEVersion(pPxNode.Id, pPxNode.NodeType, true);

about using VAR in your programming


  • var can only be used when a local variable is declared and initialized in the same statement; the variable cannot be initialized to null, or to a method group or an anonymous function.
  • var cannot be used on fields at class scope.
  • Variables declared by using var cannot be used in the initialization expression. In other words, this expression is legal: int i = (i = 20); but this expression produces a compile-time error: var i = (i = 20);
  • Multiple implicitly-typed variables cannot be initialized in the same statement.
  • If a type named var is in scope, then the var keyword will resolve to that type name and will not be treated as part of an implicitly typed local variable declaration.
You may find that var can also be useful with query expressions in which the exact constructed type of the query variable is difficult to determine. This can occur with grouping and ordering operations.
The var keyword can also be useful when the specific type of the variable is tedious to type on the keyboard, or is obvious, or does not add to the readability of the code. One example where var is helpful in this manner is with nested generic types such as those used with group operations. In the following query, the type of the query variable isIEnumerable<IGrouping<string, Student>>. As long as you and others who must maintain your code understand this, there is no problem with using implicit typing for convenience and brevity.

Finally.....


However, the use of var does have at least the potential to make your code more difficult to understand for other developers. For that reason, the C# documentation generally uses var only when it is required ! ! !

Friday, 21 October 2011

Blogging first time :)

My first day of blogging, much interesting!!! I wish to make this blog a good place to share technology, ideas, knowledge, thoughts, fun, smile etc. In fact blogging was my long time wish and finally today I believe I made it true. I have many good friends who always share knowledge, with them in circle I have started this blog believing them would keep my blogging going on for ever. My hearty thanks to everyone!!! keep blogging, cheers .