|
POST
|
Recently I noticed in the 2.0 API, there is no more LayerEvent.TILES_UPDATED, just a LayerEvent.UPDATE_END, which is great. Simplifies things quite a bit. When needing to manage Layers, i.e. - when they load and are complete, it would be great if the Flex API could dispatch a LayerEvent.UPDATE_END when layer.visible = false is peformed. I realize that visible is inherited from the UIComponent, but as of right now if you want to know that layer.visible has been set to false, you need to listen for FlexEvent.HIDE, but when layer.visible is set to true, you'll still get a LayerEvent.UPDATE_END event. That would mean that to manage visible layers in real time, I'd need to listen to 2 events from the same layer to do the same thing. Here is a code snippet that I currently use to deal with this situation.
map.addEventListener(MapEvent.LAYER_ADD, map_layerAddHandler)
protected var lyrCount:uint;
protected var lyrUpdateCount:uint;
protected function map_layerAddHandler(event:MapEvent):void {
var lyr:Layer = event.layer;
lyr.addEventListener(LayerEvent.UPDATE_END, onLayerUpdateEnd_handler);
lyr.addEventListener(FlexEvent.HIDE, function(e:Event):void{trace(e)});
lyr.addEventListener(FlexEvent.HIDE, onHide);
if (lyr.visible)
lyrCount++;
}
// I need to listen for the Hide event and manually dispatch a LayerEvent
// in order to have a proper count of current visible layers
protected function onHide(event:FlexEvent):void {
if (event.currentTarget is Layer) {
event.currentTarget.dispatchEvent(new LayerEvent(LayerEvent.UPDATE_END, event.currentTarget as Layer, null, true, false));
}
}
protected function onLayerUpdateEnd_handler(event:LayerEvent):void {
if (event.updateSuccess) {
lyrUpdateCount++;
var lyr:Layer
var tmpCount:uint = lyrCount;
lyrCount = 0;
for each (lyr in this.layers) {
if (lyr.visible)
lyrCount++;
}
trace("lyrCount",lyrCount);
trace("lyrUpdateCount",lyrUpdateCount);
trace("tmpCount",tmpCount);
if (lyrUpdateCount == lyrCount || lyrCount != tmpCount) {
lyrUpdateCount = 0;
}
}
}
It's really more of a convenience request, but it'd be nice to have. I figure since you're working on API 2.1, it couldn't hurt to ask. Thanks.
... View more
09-02-2010
08:34 AM
|
0
|
0
|
2064
|
|
POST
|
Ok, sorry. I got confused reading your earlier posts. Looking at what you have, you actually want to use a WebService, not an HTTPService. You'd use a WebService to send requests to a function and get results. An HTTPService would be used to load something like an XML or Text file. Here is an example of using a WebService with your service. Don't worry about converting to XML unless that's your thing.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="955"
minHeight="600"
applicationComplete="init()">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.soap.mxml.WebService;
protected var service:WebService;
protected function init():void {
service = new WebService();
service.showBusyCursor = true;
service.wsdl = "http://data.cmap.illinois.gov/ws/tip/tipservice.asmx?wsdl";
service.addEventListener(ResultEvent.RESULT, onResultsLoaded_handler);
service.addEventListener(FaultEvent.FAULT, onFault_handler);
service.loadWSDL();
}
protected function onFault_handler(event:FaultEvent):void {
Alert.show("Error in calling service: " + event.message, "Error");
}
protected function onResultsLoaded_handler(event:ResultEvent):void {
try {
dgResults.dataProvider = event.result as ArrayCollection;
}
catch (e:Error) {
Alert.show("An error occurred loading results: " + e.message, "Results error");
}
}
protected function btnRequest_clickHandler(event:MouseEvent):void {
service.getproject(input.text);
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout gap="5"
horizontalAlign="center"
paddingTop="25" />
</s:layout>
<s:TextInput id="input"
width="200" />
<s:Button id="btnRequest"
label="Send Request"
width="200"
click="btnRequest_clickHandler(event)" />
<mx:DataGrid id="dgResults"
width="800"
height="300" />
</s:Application>
Now as far as how this relates to the example you linked in your first post, the above will get you the ArrayCollection of results you were looking for in your first post. Now you can use those results to create a "where" query on your map service.
... View more
09-01-2010
01:28 PM
|
0
|
0
|
832
|
|
POST
|
Thanks for doing the leg work on this one Robert. I'm incorporating/tweaking your methods to create swatches into a current layer visibility component I have. Writing up/debugging those renderer symbols must have taken you forever.
... View more
09-01-2010
09:29 AM
|
0
|
0
|
1667
|
|
POST
|
Try this You can go XML -> Array or ArrayCollection Don't forget to set your result format. service.resultFormat = "e4x"; var xml:XML = event.result as XML;
var items:Array = [];
for each (var queryXML:XML in xml.tipProject) {
var obj:Object = {
project:queryXML.@project,
agency:queryXML.@agency // and so on adding the fields you want
}
items.push(obj);
} You can also turn it into an XMLListCollection var xmlListCollection:XMLListCollection = new XMLListCollection(); xmlListCollection.source = new XMLList( event.result ); You can then treat the XMLListCollection like an ArrayCollection When dealing with an HTTPService, your results are easy to parse in XML, I never used ArrayCollection with an HTTPService result, but I think the event.result object is xml by default.
... View more
08-30-2010
12:57 PM
|
0
|
0
|
1042
|
|
POST
|
An example of the .NET web service accessing an SDE could look something like this
[WebMethod(Description = "Returns Flow Control History Details")]
public DataTable FlowControlHistory(String objectID)
{
DataTable FlowTable = new DataTable();
System.Data.OleDb.OleDbConnection connection = new System.Data.OleDb.OleDbConnection("<your connection string here>");
connection.Open();
// build a sql expression to access your database data
// using a passed OBJECTID from a feature in flex
string strSQL = "SELECT DISTINCT t1.FLOWID " +
"FROM sde.SSCOMPLEXFLOWCONTROLHISTORY as t1 " +
"WHERE t1.OBJECTID = '" + objectID + "' " +
"UNION " +
"SELECT DISTINCT t2.FLOWID " +
"FROM sde.SSFLOWCONTROLHISTORY as t2 " +
"WHERE t2.OBJECTID = '" + objectID + "' " +
"ORDER BY FLOWID;
System.Data.OleDb.OleDbDataAdapter Adapter = new System.Data.OleDb.OleDbDataAdapter(strSQL, connection);
Adapter.Fill(FlowTable);
try
{
FlowTable.TableName = "Table";
}
finally
{
connection.Close();
}
return FlowTable;
}
Then in Flex, you'd do something like this.
protected var service:WebService;
protected var retry:uint = 0;
// send your Web Service WSDL to define a web service
public function setWsdl(value:String):void {
service = new WebService();
service.showBusyCursor = true;
service.wsdl = value;
service.addEventListener(FaultEvent.FAULT, WsdlFault, false, 0, true);
service.loadWSDL();
}
protected function onWsdlFault(fault:FaultEvent, token:Object = null):void {
// I always try to load a web service twice if I get a load error.
// Just in case, my network can laugh at me sometimes
retry++;
if (retry < 2)
service.loadWSDL();
else {
service.removeEventListener(FaultEvent.FAULT, WsdlFault);
Alert.show("A Web Service has failed to load. Please close the application and try again.", "Error");
}
}
// function that will call my web service
public function findRelatedFlowData(objectID:String):void {
var responder:AsyncResponder = new AsyncResponder(onFlowDataResults, onFault);
var request:AsyncToken = service.FlowControlHistory(objectID);
request.addResponder(responder);
}
proteced function onFlowDataResults(result:ResultEvent, token:Object = null):void {
var ac:ArrayCollection = result.result.Tables.Table.Rows;
// do something with results here
}
protected function onFault(fault:FaultEvent, token:Object = null):void {
// I always try to load a web service twice.
Alert.show("A Web Service error has occurred.", "Error");
}
This has always worked for me, plus by using C# or VB.NET you get a bit more control over your query. The relates in the ESRI API are still great and I use them for large data dumps, but I still have a lot of these unique queries of my SDE.
... View more
08-30-2010
06:19 AM
|
0
|
0
|
1015
|
|
POST
|
** edit, just saw that last comment you posted above. In my experience, a Web Service is quick, easy and usually a great tool for accessing external data. You could create a web service using a .NET flavor of your choice that will query your SDE or any other db to simulate your relate. Pass it a name, id, whatever. It may be a little slow depending on size of results. I've used this method for a couple of years and it works fine. Typical method for above scenario. Select graphic on map (you could also do this after getting Identify results if you'd like) Pass attribute field value to web service Use service response to populate List/DataGrid A web service is pretty simple to set up in .NET and the code is pretty easy http://msdn.microsoft.com/en-us/library/8wbhsy70.aspx Simplest route is to return a DataTable and in flex that will be returned as an ArrayCollection that will look like event.result.Tables.<TableNameHere>.Rows A benefit of doing the queries this way is that you can perform any JOINS/UNIONS or changing of field names that you may want to pass to your application to make things easier on yourself.
... View more
08-27-2010
08:37 AM
|
0
|
0
|
1015
|
|
POST
|
Relates won't work with 9.3.1 as the relationship is not recognized via the REST service.
... View more
08-27-2010
05:50 AM
|
0
|
0
|
1015
|
|
POST
|
Widget is just another name for Module. The BaseWidget class that ESRI uses in FlexViewer extends Module and adds custom fields used in FlexViewer to pass data around. So if you are looking for info on Modules in general, look up how to work with Flex Modules, loading and unloading. This will help you figure out what is happening with widgets in FlexViewer. I don't think the FlexViewer unloads the widgets when they are closed. I think they get saved to a Dictionary object.
... View more
08-26-2010
02:18 PM
|
0
|
0
|
657
|
|
POST
|
If that doesn't solve your issue, are you doing compiling via ANT?
... View more
08-26-2010
12:27 PM
|
0
|
0
|
825
|
|
POST
|
One kind of hacky way to do would probably require that you extend the Map object. Map has a UIComponent that appears to hold the layers. You can rotate this object without rotating the nav tool/logo/scalebar. But, you'd need to reset the x/y and width/height of this UIComponent to avoid having it appear as though your map has been "trimmed". That's the part that would probably require you overriding the updateDisplayList method of Map to make those changes stick, at least for width and height. You can test this out like this.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:esri="http://www.esri.com/2008/ags"
pageTitle="A tiled map service">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function map_creationCompleteHandler(event:FlexEvent):void
{
var i:int = 0;
var x:int = map.numChildren;
for (i; i < x; i++) {
if ( getQualifiedClassName(map.getChildAt(i)) == "mx.core::UIComponent") {
// if you extent the Map, you could make a mapRotate field to hold this value
map.getChildAt(i).rotation = -54;
// positioning could be tricky depending on amout rotated
map.getChildAt(i).x -= 50;
map.getChildAt(i).y = map.height/2;
map.getChildAt(i).width = map.getChildAt(i).width * 2;
map.getChildAt(i).height = map.getChildAt(i).height * 10;
}
}
}
]]>
</fx:Script>
<s:Group width="800" height="500">
<esri:Map id="map" creationComplete="map_creationCompleteHandler(event)" >
<esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"/>
</esri:Map>
</s:Group>
</s:Application>
I haven't gone any further than this to see if it would work. Maybe someone else has a simpler solution. Now that I think about, you could hide the Nav/Scalebar/Logo, just rotate the whole map and then place a separate Nav/Scalebar outside the map. With the 2.0 API, we now have a ScaleBar object that you just set the map for and you're good to go. That's probably an easier solution than trying to fuss with extending the Map. This method is probably easier.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:esri="http://www.esri.com/2008/ags"
pageTitle="A tiled map service"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:layout>
<s:VerticalLayout />
</s:layout>
<s:BorderContainer borderColor="0x000000">
<s:Group id="grpMap"
width="400"
height="400">
<esri:Map id="map"
logoVisible="false"
scaleBarVisible="false"
x="-389"
y="337"
rotation="-54" width="1000" height="1000">
<esri:ArcGISTiledMapServiceLayer url="http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
</esri:Map>
</s:Group>
<s:Scroller horizontalScrollPolicy="off"
verticalScrollPolicy="off"
viewport="{grpMap}" />
</s:BorderContainer>
<s:Group>
<s:layout>
<s:HorizontalLayout />
</s:layout>
<esri:Navigation map="{map}" />
<esri:ScaleBar map="{map}"
verticalCenter="0" />
</s:Group>
</s:Application>
Still, to implement this, you'd probably want to do some math to size and position the map in the container just right. I'm not sure how simply turn Nav off in the Map either.
... View more
08-25-2010
01:06 PM
|
0
|
0
|
743
|
|
POST
|
That is odd. Tried adding a rotation to this example http://help.arcgis.com/en/webapi/flex/samples/index.html?sample=TiledMap and it just doesn't like it. Can't even zoom to the layer properly.
... View more
08-25-2010
10:38 AM
|
0
|
0
|
743
|
|
POST
|
There are a couple of options. In the Flex API, there is a DrawingInfo field for LayerDetails. You can grab the renderer from there. Mr. Scheitlin has a great example of this in his DynamicLegendWidget. If you go through his widget, you can see how he parses the LayerDetails to get this information.
... View more
08-23-2010
12:51 PM
|
0
|
0
|
506
|
|
POST
|
I tried your code using Flex 3.6 nightly build and it worked fine. So the issue appears to be a 3.5 bug.
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
protected var ac:ArrayCollection = new ArrayCollection([{name:"Bob",
children:["bobby", "sally", "billy"]},
{name:"Sarah",
children:["angie","kelly"]},
{name:"Sam",
children:["sammy","roger","troy", "rich"]}]);
]]>
</mx:Script>
<mx:ComboBox id="areaCB"
labelField="name"
dataProvider="{ac}" />
<mx:ComboBox id="teamCB"
dataProvider="{areaCB.selectedItem.children}"
labelField="Team" />
</mx:HBox>
You're best bet is to either downgrade to 3.4 or move to 3.6.
... View more
08-05-2010
10:21 AM
|
0
|
0
|
1185
|
|
POST
|
Hi Casey, There is a similar case noted on the Adobe forums with syncing ComboBoxes using SDK 3.5 I can repeat the bug in this thread in the 3.5 SDK that ships with FlashBuilder 4. http://forums.adobe.com/message/2642802 It may be related. Can you provide a sample of the ArrayCollection? I think I still have some nightly builds I can test against.
... View more
08-05-2010
09:06 AM
|
0
|
0
|
1185
|
|
POST
|
You can try calling areaChange on the close event, but I think the issue might be that since you have combobox 2 bound to an object in the selected item of combobox 1, you don't need to make the function call at all. Try removing the areaChange call where you set the dataProvider to null. You shouldn't need it.
... View more
08-05-2010
07:29 AM
|
0
|
0
|
1185
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | a week ago | |
| 1 | 12-09-2025 08:20 AM | |
| 1 | 11-13-2025 03:13 PM | |
| 2 | 11-06-2025 11:10 AM | |
| 3 | 11-05-2025 02:54 PM |
| Online Status |
Offline
|
| Date Last Visited |
Thursday
|