} // public void Execute(object parameter)

        /// <summary>
        /// Executes the relationship query against the layer.
        /// </summary>
        /// <param name="parameter">The OnClickPopupInfo from the layer.</param>
        public void doExecute(object parameter)
        {
            // The plan is:
            // Get the featurelayer and clicked feature from the pop-up.
            // The PopupItem property of OnClickPopupInfo provides information
            // about the item currently shown in the pop-up.
            // Then get feature ID value and put it into ExecuteRelationshipQueryAsync task.
            // Then get related records ID's and create FeatureLayer from
            // related table/feature class, filtered by that ID's.
            // Then show grid for that layer.
            popupInfo    = parameter as OnClickPopupInfo;
            inputFeature = popupInfo.PopupItem.Graphic;
            var lyr = new VUtils.ArcGIS.SLViewer.VLayer(popupInfo.PopupItem.Layer);

            // print layer info to console
            log(string.Format(
                    "Execute, layer type '{0}', popupInd '{1}', popupDescr '{2}', lyrID '{3}', lyrName '{4}', title '{5}'",
                    popupInfo.PopupItem.Layer.GetType(),
                    popupInfo.SelectedIndex, popupInfo.SelectionDescription,
                    popupInfo.PopupItem.LayerId, popupInfo.PopupItem.LayerName, popupInfo.PopupItem.Title));
            log(string.Format("Execute, lyrType '{0}', lyrUrl '{1}'", lyr.lyrType, lyr.lyrUrl));
            log(string.Format("Execute, inputFeature.Attributes.Count '{0}'", inputFeature.Attributes.Count));

            // we need FeatureLayer
            if (lyr.lyrType == "FeatureLayer")
            {
                // The layer to get related records for.
                // This is used to get the RelationshipID and Query url.
                relatesLayer = lyr.lyr as FeatureLayer;
            }
            else if (lyr.lyrType == "ArcGISDynamicMapServiceLayer")
            {
                var rLyr = getSubLayer(lyr, popupInfo.PopupItem.LayerId) as FeatureLayer;
                if (relatesLayer != null && relatesLayer.Url == rLyr.Url)
                {
                    // we're here after relatesLayer.Initialized
                    ;
                }
                else
                {
                    // init new FeatureLayer
                    relatesLayer              = rLyr;
                    relatesLayer.Initialized += (a, b) => {
                        if (relatesLayer.InitializationFailure == null)
                        {
                            var info = relatesLayer.LayerInfo;
                            log(string.Format(
                                    "Execute, relatesLayer.InitializationFailure == null, info '{0}'",
                                    info));
                            Execute(parameter);
                        }
                    }; // callback
                    relatesLayer.Initialize();
                    log(string.Format("Execute, relatesLayer.Initialize called, wait..."));
                    return;
                } // init new FeatureLayer
            }     // if(lyr.lyrType == "ArcGISDynamicMapServiceLayer")
            else
            {
                throw new Exception("Layer type must be FeatureLayer or ArcGISDynamicMapServiceLayer");
            }

            // we have inited FeatureLayer now
            if (relatesLayer.LayerInfo == null)
            {
                throw new Exception(string.Format("Execute, relatesLayer.LayerInfo == null"));
            }
            var clickedLayer = new VUtils.ArcGIS.SLViewer.VLayer(relatesLayer);

            // check FeatureLayer info
            log(string.Format(
                    "Execute, relatesLayer lyrType '{0}', lyrUrl '{1}'",
                    clickedLayer.lyrType, clickedLayer.lyrUrl));

            // get relationship id
            var rels = relatesLayer.LayerInfo.Relationships;

            if (rels.Count() <= 0)
            {
                log(string.Format("Execute, relationships.count <= 0"));
                throw new Exception(string.Format("Layer have not relations"));
            }
            else if (rels.Count() > 1)
            {
                log(string.Format("Execute, relationships.count > 1"));
                if (relationsListForm.listBox1.Items.Count > 0)
                {
                    // continue after user input
                    // user selected relID already
                    relationInfo = new VUtils.ArcGIS.SLViewer.VRelationInfo(
                        relationsListForm.listBox1.SelectedItem as string);
                    relationsListForm.listBox1.Items.Clear();
                }
                else
                {
                    // new query
                    foreach (var r in rels)
                    {
                        var ri = new VUtils.ArcGIS.SLViewer.VRelationInfo(r);
                        relationsListForm.listBox1.Items.Add(ri.descr);
                    }
                    relationsListForm.listBox1.SelectedItem = relationsListForm.listBox1.Items.First();
                    MapApplication.Current.ShowWindow("Relations",
                                                      relationsListForm,
                                                      false, // ismodal
                                                      (sender, canceleventargs) => {
                        log("relationsListForm onhidINGhandler");
                    },     // onhidinghandler
                                                      (sender, eventargs) => {
                        log("relationsListForm onhidEhandler");
                        if (relationsListForm.listBox1.SelectedItem != null)
                        {
                            Execute(parameter);
                        }
                    },     // onhidehandler
                                                      WindowType.Floating
                                                      );
                    return; // wait for user input
                } // new query
            } // rels.count > 1
            else   // rels.count == 1
            {
                log(string.Format("Execute, relationships.count = 1"));
                relationInfo = new VUtils.ArcGIS.SLViewer.VRelationInfo(rels.First());
            }

            // ok, we get relation info now
            log(string.Format(
                    "Execute, getrelid, relationshipID '{0}', rels.count '{1}'",
                    relationInfo.id, rels.Count()));

            // Get the name of the ObjectID field.
            objectID = relatesLayer.LayerInfo.ObjectIdField;
            string objectIDAlias = clickedLayer.getFieldAlias(objectID);

            log(string.Format("Execute, objectID '{0}', alias '{1}'", objectID, objectIDAlias));
            if (objectIDAlias != "")
            {
                objectID = objectIDAlias;                     // because of bug? in Graphic.Attributes[fieldname]
            }
            // get key value
            Object v = null;

            v = inputFeature.Attributes[objectID];
            log(string.Format("Execute, objIdValue.str='{0}'", v));
            int objIdValue = -1;

            try {
                objIdValue = Int32.Parse(string.Format("{0}", v));
            }
            catch (Exception ex) {
                // fieldname = 'OBJECTID' but alias = 'Object ID'
                var ks = string.Join(", ", inputFeature.Attributes.Keys);
                var vs = string.Join(", ", inputFeature.Attributes.Values);
                log(string.Format("Execute, inputFeature.AttributesKeys='{0}', values='{1}'", ks, vs));
                throw new Exception(string.Format("OBJECTID is not an integer"));
            }
            log(string.Format("Execute, objIdValue.int='{0}'", objIdValue));

            // Input parameters for QueryTask
            RelationshipParameter relationshipParameters = new RelationshipParameter()
            {
                ObjectIds      = new int[] { objIdValue },
                OutFields      = new string[] { "*" }, // Return all fields
                ReturnGeometry = true,                 // Return the geometry
                // so that features can be displayed on the map if applicable

                RelationshipId = relationInfo.id, // Obtain the desired RelationshipID
                // from the Service Details page. Here it takes the first relationship
                // it finds if there is more than one.

                OutSpatialReference = MapApplication.Current.Map.SpatialReference
            };

            // Specify the Feature Service url for the QueryTask.
            queryTask.Url = relatesLayer.Url;

            //  Execute the Query Task with specified parameters
            queryTask.ExecuteRelationshipQueryAsync(relationshipParameters);

            // Find the attribute grid in the Pop-up and insert the BusyIndicator
            attributeGrid = Utils.FindChildOfType <Grid>(popupInfo.AttributeContainer, 3);
            indicator     = new BusyIndicator();
            if (attributeGrid != null)
            {
                // Add the Busy Indicator
                attributeGrid.Children.Add(indicator);
                indicator.IsBusy = true;
            }

            log(string.Format("Execute, completed, wait for QueryTask_ExecuteRelationshipQueryCompleted"));
        } // public void doExecute(object parameter)