|
POST
|
Thank you Johnny, looks exactly like what I need. Will give it a try. Terry
... View more
09-19-2011
05:46 AM
|
0
|
0
|
423
|
|
POST
|
I'd like to alter my legend control so that the user can right click on a map service or a layer within a map service, get a context menu with a "What's this?" option which will return the Service or Layer description from the map service (via webclient.downloadstringasynch()...). I've done similar things with TreeView controls in the past but they have an actual RightMouseButtonDown event - LayerItemViewModels do not as far as I can see. Is it possible to wire a mouse event to the Legend's controls? If so, can I get a hint in the right direction? Thanks, Terry
... View more
09-16-2011
01:54 PM
|
0
|
2
|
903
|
|
POST
|
Hi all, I posted this on the ArcGIS general forum a month ago but never got any response. Hopefully someone more familiar with Data Interop than I am can help me resolve my issue. I've set up an Interop connection to a WFS service and am seeing odd behavior when applying a filter. Basically what I need to do if filter the data to multiple states for a given survey type. Bascially an expression like this -
(state_code = "MT" or state_code = "SD" or state_code = "ND" or state_code = "NE" ) AND (survey = "type1")
I can get the filter to work when I only provide 2 states but when I try to put 3 states in the OR statement I get the usual error stating "The dataset appears to be invalid. Please verify your settings ... and try again". Am I writing the OR statement incorrectly or is this a known issue with either ArcGIS or the WFS standards? The 2 versions of the filters are below & I'm using ArcGIS v10.0 Thanks, Terry 2 states only - works
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:And>
<ogc:Or>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>STATE_CODE</ogc:PropertyName>
<ogc:Literal>NE</ogc:Literal>
</ogc:PropertyIsEqualTo>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>STATE_CODE</ogc:PropertyName>
<ogc:Literal>MT</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Or>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>SURVEY_NAME</ogc:PropertyName>
<ogc:Literal>Type1</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:And>
</ogc:Filter>
3 states in the OR - fails
<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc">
<ogc:And>
<ogc:Or>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>STATE_CODE</ogc:PropertyName>
<ogc:Literal>NE</ogc:Literal>
</ogc:PropertyIsEqualTo>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>STATE_CODE</ogc:PropertyName>
<ogc:Literal>MT</ogc:Literal>
</ogc:PropertyIsEqualTo>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>STATE_CODE</ogc:PropertyName>
<ogc:Literal>WY</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Or>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>SURVEY_NAME</ogc:PropertyName>
<ogc:Literal>Type1</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:And>
</ogc:Filter>
... View more
09-09-2011
01:02 PM
|
0
|
1
|
874
|
|
POST
|
Hello Dominique, Adding the legend to a user control & thus the visual tree did the trick. A huge THANK YOU to both you and Jennifer. So far in testing the legend is always ready by the time I get to printing the 2nd page. Modified code below in case it helps anyone else. I made 3 other short changes - added a busy indicator, added a checkbox so the user could skip printing the legend (smaller export size), and set the Legend's background to white instead of the default gradient also for smaller export size & cleaner printing. Thanks again, Terry
private void btnOK_Click(Object sender, RoutedEventArgs e)
{
busy.IsBusy = true;
_LayerComplete = 0;
_LayerCount = 0;
//get map and legend prep'd
_pp = _Parent.Printpage;
_pp.setMap(_Map);
_pp.Visibility = Visibility.Visible;
(_pp.LayoutRoot.FindName("txtTitle") as TextBlock).Text = txtTitle.Text;
(_pp.LayoutRoot.FindName("txtDate") as TextBlock).Text = "Created: " + DateTime.Now.ToShortDateString();
_lgnd = new Legend();
_ppl = _Parent.PrintLegend;
_ppl.LayoutRoot.Children.Add(_lgnd);
_lgnd.ShowOnlyVisibleLayers = true;
_lgnd.LayerItemsMode = Legend.Mode.Tree;
_lgnd.Map = _pp.mapPrint;
_lgnd.Refreshed += _lgnd_Refreshed;
_lgnd.Background = new SolidColorBrush(Colors.White); //overwrite default gradient - smaller output size
//drop tiled services since they dont have a legend with symbology
List<string> layIDs = new List<string>();
foreach (Layer lyr in _pp.mapPrint.Layers.Where(t => !(t is ArcGISTiledMapServiceLayer)))
{
layIDs.Add(lyr.ID);
_LayerCount++;
}
layIDs.Reverse();
_lgnd.LayerIDs = layIDs.ToArray();
_doc = new PrintDocument();
_doc.PrintPage += doc_PrintPage1;
_doc.EndPrint += doc_EndPrint;
_doc.Print("AweMap_" + txtTitle.Text);
}
void _lgnd_Refreshed(object sender, Legend.RefreshedEventArgs e)
{
//see if LIVM that fired refreshed is no longer busy; increment layer complete counter
e.LayerItem.PropertyChanged += (s,evnt) =>
{
if ( (!(s as LayerItemViewModel).IsBusy) && evnt.PropertyName.ToLower() == "isbusy")
{
_LayerComplete++;
}
};
}
void doc_PrintPage1(object sender, PrintPageEventArgs args)
{
_pp.Width = args.PrintableArea.Height;
_pp.Height = args.PrintableArea.Width;
_pp.UpdateLayout();
if (rbLand.IsChecked.GetValueOrDefault(true))
{
//rotate to landscape
TransformGroup transformGroup = new TransformGroup();
transformGroup.Children.Add(new RotateTransform() { Angle = 90 });
transformGroup.Children.Add(new TranslateTransform() { X = args.PrintableArea.Width });
_pp.RenderTransform = transformGroup;
}
args.PageVisual = _pp;
//see if user selected to include legend:D
if (chkLegend.IsChecked.GetValueOrDefault(true))
{
//swap handler for 2nd page w/ legend control
_doc.PrintPage -= doc_PrintPage1;
_doc.PrintPage += doc_PrintPage2;
args.HasMorePages = true;
}
else
{
args.HasMorePages = false;
}
}
void doc_PrintPage2(object sender, PrintPageEventArgs args)
{
_pp.Width = args.PrintableArea.Height;
_pp.Height = args.PrintableArea.Width;
_lgnd.Width = _ppl.Width - 50;
_lgnd.Height = _ppl.Height - 50;
if (_LayerComplete < _LayerCount)
{
System.Diagnostics.Debug.WriteLine("Waiting for Legend...");
System.Threading.Thread.Sleep(1000);
args.PageVisual = null;
args.HasMorePages = true;
}
else
{
args.PageVisual = _lgnd;
args.HasMorePages = false;
}
}
... View more
08-31-2011
07:55 AM
|
0
|
0
|
891
|
|
POST
|
Hi Jennifer & Dominique, Thanks for the reviewing my code and the suggestions. I still cannot explain why the legend's LayerItems is null as the string array layIds is populated correctly using the code snippet I posted below - I've stepped through it in debug mode & piped it out using System.Diagnostics.Debug.WriteLine and it's contains the names of the layers I would expect. I'm now trying to hook into the legend's refreshed event as you suggested but am having problems here, which I believe are related to how I'm trying to tie everything together, since I'm trying to print 2 pages. The basic logic flow (code is below) is currently as follows - user clicks btnPrint; create a new legend in code, tie it to a map on a user control (_pp.mapPrint in the code) & add a handler to its Refreshed event; create a new PrintDocument and add a handler for it's PrintPage event; call PrintDocument.Print() PrintPage handler fires - sets the user control with the map to the PrintPageEventArgs PageVisual property; Remove the current PrintPage handler & add PrintPage2 handler in PrintPage2 handler set the Legend's LayerIDs to just the non-tiled map services in the map (here's where I stuck) .... try to wait for the Legend refreshed to fire and examine the IsBusy property of the LayerItemViewModel which fired the Refresh - increment a counter tracking how many are complete when counter of complete == counter of # of map layers pass the Legend to the PrintPageEventArgs PageVisual property and reset HasMorePages to false so the doc will print I seem to not be catching the Legend refreshed event properly - is this a threading issue or is my logic flawed, or both?? Thanks again for the help! Terry
private void btnOK_Click(Object sender, RoutedEventArgs e)
{
_LayerComplete = 0;
_LayerCount = 0;
//get map and legend prep'd
_pp = _Parent.Printpage;
_pp.setMap(_Map);
_pp.Visibility = Visibility.Visible;
(_pp.LayoutRoot.FindName("txtTitle") as TextBlock).Text = txtTitle.Text;
(_pp.LayoutRoot.FindName("txtDate") as TextBlock).Text = "Created: " + DateTime.Now.ToShortDateString();
_lgnd = new Legend();
_lgnd.ShowOnlyVisibleLayers = true;
_lgnd.LayerItemsMode = Legend.Mode.Tree;
_lgnd.Map = _pp.mapPrint;
_lgnd.Refreshed += _lgnd_Refreshed;
_doc = new PrintDocument();
_doc.PrintPage += doc_PrintPage1;
_doc.EndPrint += doc_EndPrint;
_doc.Print("AweMap_Export");
}
void _lgnd_Refreshed(object sender, Legend.RefreshedEventArgs e)
{
e.LayerItem.PropertyChanged += (s,evnt) =>
{
if (!(s as LayerItemViewModel).IsBusy)
{
System.Diagnostics.Debug.WriteLine((s as LayerItemViewModel).Layer.ID + " is no longer busy");
_LayerComplete++;
}
else
{
System.Diagnostics.Debug.WriteLine((s as LayerItemViewModel).Layer.ID + " is busy");
}
};
//have also tried this with no luck -
//if (!e.LayerItem.IsBusy)
//{
// System.Diagnostics.Debug.WriteLine(e.LayerItem.Layer.ID + " is no longer busy");
// _LayerComplete++;
//}
//else
//{
// System.Diagnostics.Debug.WriteLine(e.LayerItem.Layer.ID + " is busy");
//}
}
void doc_PrintPage1(object sender, PrintPageEventArgs args)
{
System.Diagnostics.Debug.WriteLine("start of page1 print)");
_pp.Width = args.PrintableArea.Height;
_pp.Height = args.PrintableArea.Width;
_pp.UpdateLayout();
if (rbLand.IsChecked.GetValueOrDefault(true))
{
//rotate to landscape
TransformGroup transformGroup = new TransformGroup();
transformGroup.Children.Add(new RotateTransform() { Angle = 90 });
transformGroup.Children.Add(new TranslateTransform() { X = args.PrintableArea.Width });
_pp.RenderTransform = transformGroup;
}
//swap handler for 2nd page w/ legend control
_doc.PrintPage -= doc_PrintPage1;
_doc.PrintPage += doc_PrintPage2;
args.PageVisual = _pp;
args.HasMorePages = true;
}
void doc_PrintPage2(object sender, PrintPageEventArgs args)
{
System.Diagnostics.Debug.WriteLine("start of page2 print)");
//drop tiled services since they dont have a legend with symbology
List<string> layIDs = new List<string>();
foreach (Layer lyr in _pp.mapPrint.Layers.Where(t => !(t is ArcGISTiledMapServiceLayer)))
{
layIDs.Add(lyr.ID);
_LayerCount++;
}
layIDs.Reverse();
_lgnd.LayerIDs = layIDs.ToArray();
//code below doesn't seem to change outcome, although if I don't set _lgnd.LayerIDs above the LayerItems will be null in the loop below..
//foreach (Layer lyr in _pp.mapPrint.Layers.Where(t => !(t is ArcGISTiledMapServiceLayer)))
//{
// _LayerCount++;
// LayerItemViewModel livm = new LayerItemViewModel(lyr);
// // livm.PropertyChanged += livm_PropertyChanged;
// _lgnd.LayerItems.Add(livm);
//}
int lcnt = 0;
int lcomp = -1;
while (lcomp < lcnt)
{
// this results in an endless loop as _LayerComplete is never updated
lcnt = _LayerCount;
lcomp = _LayerComplete;
}
args.PageVisual = _lgnd;
args.HasMorePages = false;
}
... View more
08-30-2011
02:14 PM
|
0
|
0
|
891
|
|
POST
|
Do you need the unique values for just one feature or from a given attribute in several features? If you just want the unique values across all attributes in one feature you could do something like this -
List<string> values = new List<string>();
foreach (var item in feature.Attributes)
{
if (!values.Contains(item.Value.ToString()))
{
values.Add(item.Value.ToString());
}
}
If you need to get the unique values from a series of features see this forum thread - http://forums.arcgis.com/threads/36312-Attribute-Query-Distinct-values?p=127568#post127568. It's not fast if you have a large number of features to handle but it works. Terry
... View more
08-26-2011
10:16 AM
|
0
|
0
|
355
|
|
POST
|
Thanks for the idea Jennifer. I'm working on that but am don't doing something correctly I think. My current code is below where I'm creating the legend and trying to hook into the PropertyChanged event for each LayerItemViewModel in the legend but my handler never fires. Looking in to it some more, my Legend's LayerItems collection is null, but the LayerIDs are correct and I've been using that to drop out Tiled MapServices as they don't have a legend with symbology. Am I missing something in how I'm creating the legend? Thanks again, Terry
//_pp is a user control with the map on it I print
private void btnOK_Click(Object sender, RoutedEventArgs e)
{
_LayerComplete = 0;
_LayerCount = 0;
//get map and legend prep'd
_pp = _Parent.Printpage;
_pp.setMap(_Map);
_lgnd = new Legend();
_lgnd.ShowOnlyVisibleLayers = true;
_lgnd.LayerItemsMode = Legend.Mode.Tree;
_lgnd.Map = _pp.mapPrint;
(_pp.LayoutRoot.FindName("txtTitle") as TextBlock).Text = txtTitle.Text;
(_pp.LayoutRoot.FindName("txtDate") as TextBlock).Text = "Created: " + DateTime.Now.ToShortDateString();
//drop tiled services since they dont have a legend with symbology
List<string> layIDs = new List<string>();
foreach (var lyr in _pp.mapPrint.Layers)
{
if (!(lyr is ArcGISTiledMapServiceLayer))
{
layIDs.Add(lyr.ID);
}
}
layIDs.Reverse();
_lgnd.LayerIDs = layIDs.ToArray();
foreach (LayerItemViewModel livm in _lgnd.LayerItems)
{
livm.PropertyChanged += livm_PropertyChanged; //never happens LayerItems is empty
}
}
void livm_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
MessageBox.Show(e.PropertyName + " changed");
//real code should see which prop changed..if B
}
... View more
08-26-2011
07:52 AM
|
0
|
0
|
891
|
|
POST
|
I have a button in my application which allows the user to print the map using the standard Silverlight PrintDocument class (acutally it 'clones' the map onto another user control which looks like our standard map tempalte). I'm trying to add a 2nd page to the print doc which contains a legend control. I'm able to get the 2nd page to print but the legend control aways has the busy indicator next to the layer names (see attached image). Is there a way to track when the legend has completed building it's tree and contains the layer/sublayer names & symbology? The only other way I can think to do it is to use WebClient.DownloadStringAsynch() against each layer's legend (http://server/arcgis/rest/services/Service/Legend?f=pjson) and pull out the layer names and image bytes and put them into my own TreeView... Anyone have any other ideas? Thanks, Terry
... View more
08-25-2011
11:09 AM
|
0
|
7
|
1363
|
|
POST
|
While there is no direct way to do it in the Silverlight API or in REST, it is possible even if the layer you're querying has more features than the max # Features set on the service. Starting in version 10 you can query with the option to just retreive the ObjectIDs of the features that match your query. Since you're not returning features this way, the maximum # of features limitation is bypassed. Below is some simple example XAML and C# code to do exactly this in a 2 step approach - 1. Get all the object IDs from the layer. Can be done using a query that is true for all features such as query.where = "1=1" 2. Pull the objectIDs out in chunks of 1000 (the default max # of features for a v10 Server) and run a query that'll actually get the attribute(s) you need back & create a list of unique values from it. I wrote this up today as it's something I've been needing to do for a user but have been putting off and to hopefuly help gbushek and others. Also turned out to be a fun learning experience with some LINQ too.. I tested this against a layer with 34,000 + features in it. Just getting the values from 1 field takes around 10 seconds to complete. The code below actually grabs 2 fields (county and state) from the data to build the list and takes closer to 15-20 seconds. Not the usual snappy response I'm used to with Silverlight but it does work. There are of course other options, depending on your data sources - WCF service calls or using SQL to LINQ and the Entity Framework come to mind. I'm also sure some of my code below code be more efficient but it's a start.... if anyone can speed it up, I'd love to hear about it. Terry XAML
<UserControl x:Class="ArcGISSilverlightSDK.RoutingDirections"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:toolkit= "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit"
xmlns:esri="http://schemas.esri.com/arcgis/client/2009">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.Resources>
<esri:SimpleMarkerSymbol x:Key="FromSymbol" Size="15" Style="Circle" Color="#9900FF00" />
<esri:SimpleMarkerSymbol x:Key="ToSymbol" Size="15" Style="Circle" Color="#99FF0000" />
<esri:SimpleLineSymbol x:Key="RouteSymbol" Color="#990000FF" Width="5"/>
<esri:SimpleLineSymbol x:Key="SegmentSymbol" Color="#99FF0000" Width="8"/>
</Grid.Resources>
<Grid.RowDefinitions>
<!--<RowDefinition Height="30" />-->
<RowDefinition Height="75" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<toolkit:BusyIndicator x:Name="busy" IsBusy="False">
<StackPanel Orientation="Horizontal" >
<Button x:Name="btnTest" Content="pop cbox" Click="btnTest_Click" Width="75" Height="50" />
<ComboBox x:Name="cbxValues" Grid.Column="2" Grid.Row="1" Width="100" Height="50" />
</StackPanel>
</toolkit:BusyIndicator>
</Grid>
</UserControl>
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Tasks;
namespace ArcGISSilverlightSDK
{
public partial class RoutingDirections : UserControl
{
public RoutingDirections()
{
InitializeComponent();
}
private int _featcount;
private int _featcomplete;
private List<string> uniquevalues;
private void btnTest_Click(object sender, RoutedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("start " + System.DateTime.Now);
busy.IsBusy = true;
uniquevalues = new List<string>();
QueryTask qt = new QueryTask("http://myserver/ArcGIS/rest/services/MyService/MapServer/0");
qt.ExecuteCompleted += qt_ExecuteCompleted;
qt.Failed += qt_Failed;
Query qry = new Query();
qry.ReturnIdsOnly = true;
qry.Where = "1=1"; //get them all... ReturnIDsonly is not limited to the max #features set for a sevice
qt.ExecuteAsync(qry, qt.Url);
}
void qt_Failed(object sender, TaskFailedEventArgs e)
{
MessageBox.Show(e.Error.Message);
}
void qt_ExecuteCompleted(object sender, QueryEventArgs e)
{
_featcount += e.FeatureSet.ObjectIDs.Count();
if (_featcount == 0)
{
return;
}
int[] oids;
QueryTask qt = new QueryTask("http://myserver/ArcGIS/rest/services/MyService/MapServer/0");
Query qry = new Query();
//assuming max # features returned is stilll the v10.0 default of 1000 here....
for (int i = 0; i <= Math.Floor(_featcount / 1000); i++)
{
oids = e.FeatureSet.ObjectIDs.Skip(i * 1000).Take(1000).Select(x => int.Parse(x.ToString())).ToArray();
qt = new QueryTask("http://myserver/ArcGIS/rest/services/MyService/MapServer/0");
qt.ExecuteCompleted += fullqt_ExecuteCompleted;
qt.Failed += qt_Failed;
qry = new Query();
OutFields ofld = new OutFields();
ofld.Add("COUNTYNAME");
ofld.Add("STATE");
qry.OutFields = ofld;
qry.ObjectIDs = oids;
qt.ExecuteAsync(qry);
}
}
void fullqt_ExecuteCompleted(object sender, QueryEventArgs e)
{
foreach (Graphic g in e.FeatureSet)
{
_featcomplete += 1;
if (!uniquevalues.Contains(g.Attributes["COUNTYNAME"].ToString() + ", " + g.Attributes["STATE"].ToString()))
{
uniquevalues.Add(g.Attributes["COUNTYNAME"].ToString() + ", " + g.Attributes["STATE"].ToString());
}
}
if (_featcomplete == _featcount)
{
cbxValues.ItemsSource = uniquevalues;
System.Diagnostics.Debug.WriteLine("done " + System.DateTime.Now);
busy.IsBusy = false;
cbxValues.IsDropDownOpen = true;
}
}
}
}
... View more
08-19-2011
12:31 PM
|
0
|
0
|
622
|
|
POST
|
The code below is in the legend's Refreshed event and should collapse all nodes under each layer. Not sure on the check boxes - maybe rebind the the map property of the legend?
private void mapLegend_Refreshed(object sender, Legend.RefreshedEventArgs e)
{
CollapseLayerItems(e.LayerItem);
}
private void CollapseLayerItems(LayerItemViewModel livm)
{
//collapses a node in the legend tree and all of its sub layers recursively
livm.IsExpanded = false;
if (livm.LayerItems != null)
{
foreach (LayerItemViewModel sublayerItemVM in livm.LayerItems)
{
CollapseLayerItems(sublayerItemVM);
}
}
}
... View more
08-15-2011
12:28 PM
|
0
|
0
|
456
|
|
POST
|
try using a Geometry Service and it's RelationAsync method. You can pass in the geometries from the polygon and pivot graphics and GeometryRelation = esriGeometryRelationIn. Here's a sample from ESRI using points inside polygons but same logic - http://help.arcgis.com/en/webapi/silverlight/samples/start.htm#Relation
... View more
08-12-2011
09:11 AM
|
0
|
0
|
359
|
|
POST
|
Rick, What kind of layer is it? If it's a ArcGISDynamicMapServiceLayer also try setting the DisableClientCaching property to true, then call refresh. Worked for me to refresh an event layer after the user updates lat-longs in a SQL Server table as described here - http://forums.arcgis.com/threads/31439-Refreshing-map-or-layer-display
... View more
08-09-2011
02:12 PM
|
0
|
0
|
810
|
|
POST
|
I have a simple script (below) which copies data from a Data Interop connection to a new file geodatabase. The script works fine in ArcMap's python window and in Idle but crashes PythonWin (see attached), which is what I prefer to work in. I'm running Win 7 (64bit), Python 2.6 (installed w/ ArcGIS), PythonWin build 212 (32bit, installed from the ArcGIS install disk), and ArcGIS 10 SP 2 with an ArcInfo license. Anyone have any ideas why this might happen & how I can fix it? Thanks, Terry
import arcpy, datetime, string
strInterop = 'Interoperability Connections\\IPHIS.fdl\\Samples'
strFolder = 'X:/Central/Temp'
strBase = 'iphis_' + string.replace(str(datetime.date.today()),'-','')
strDB = strBase + '.gdb'
arcpy.management.CreateFileGDB(strFolder,strDB,'9.3') #crashes here in PythonWin
arcpy.management.CopyFeatures(strInterop,strFolder + '/' + strDB + '/' + strBase)
... View more
08-09-2011
02:04 PM
|
0
|
0
|
741
|
|
POST
|
Thanks Patrick I saw that blog earlier today too. In the end I changed from trying to pass the objects to just passing their properties I needed (point.X map.Width, etc..) as primative types (string, double, etc...). Also found a good summary of what works with the DataContractSerializer from Microsoft here - http://msdn.microsoft.com/en-us/library/cc656732.aspx
... View more
08-04-2011
01:22 PM
|
0
|
0
|
623
|
|
POST
|
Hi all, I'm working on a custom ID tool to work against WMS layers in my map. I've set up a WCF service to do most of the work but when I pass in an object (FeatureInfoParams, definition below) only the string/int properties are populated, I lose the objects (ESRI Envelope, System.Windows.Point, & System.Windows.Rect). What do I need to change in my class to get these from the client to the server? Thanks, Terry server side - side question - If I do not mark the WMSQuery class with the [XmlSerializerFormat] attribute I get a generic "Communicators error - Not found" when I call the GetFeatureInfoAsynch client side. Anyone know why?
namespace AWEMap.Web
{
[ServiceContract(Namespace = "AWEMap.Web")]
[XmlSerializerFormat]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class WMSQuery
{
[OperationContract]
public void GetFeatureInfo(FeatureInfoParams FIParams)
{
WebClient web = new WebClient();
string strGetFeat = FIParams.Url + "?REQUEST=GetFeatureInfo&SERVICE=WMS&VERSION=" + FIParams.Version;
strGetFeat += "&Layers=" + FIParams.Layers;
strGetFeat += "&STYLES=default&FORMAT=image/png&BGCOLOR=0xFFFFFF&TRANSPARENT=TRUE";
strGetFeat += "&BBOX=" + FIParams.Extent.XMin + "," + FIParams.Extent.YMin + "," + FIParams.Extent.XMax + "," + FIParams.Extent.YMax;
strGetFeat += "&WIDTH=" + FIParams.Map.Width + "&HEIGHT=" + FIParams.Map.Height;
strGetFeat += "&QUERY_LAYERS=" + FIParams.Layers;
if (FIParams.Version == "1.3.0")
{
strGetFeat += "&CRS=EPSG:" + FIParams.SRID;
strGetFeat += "&I=" + FIParams.Point.X + "&J=" + FIParams.Point.Y;
}
else
{
strGetFeat += "&SRS=EPSG:" + FIParams.SRID;
strGetFeat += "&X=" + FIParams.Point.X + "&Y=" + FIParams.Point.Y;
}
...... more code here to handle XML returned by webclient....
}
}
[DataContract(Namespace = "AWEMap.Web")]
public class FeatureInfoParams : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public FeatureInfoParams() { }
private string _url;
private string _version;
private string _layers;
private int _srid;
private Envelope _extent;
private Rect _map;
private Point _point;
[DataMember]
public string Url
{
get { return _url; }
set { _url = value; NotifyPropertyChanged("Url"); }
}
[DataMember]
public string Version
{
get { return _version; }
set { _version = value; NotifyPropertyChanged("Version"); }
}
[DataMember]
public string Layers
{
get { return _layers; }
set { _layers = value; NotifyPropertyChanged("Layers"); }
}
[DataMember]
public int SRID
{
get { return _srid; }
set { _srid = value; NotifyPropertyChanged("SRID"); }
}
[DataMember]
public Envelope Extent
{
get { return _extent; }
set { _extent = value; NotifyPropertyChanged("Extent"); }
}
[DataMember]
public Rect Map
{
get { return _map; }
set { _map = value; NotifyPropertyChanged("Map"); }
}
[DataMember]
public Point Point
{
get { return _point; }
set { _point = value; NotifyPropertyChanged("Point"); }
}
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
client side
WLyr = (_Map.Layers as WmsLayer);
WMSQueryService.WMSQueryClient client = new WMSQueryService.WMSQueryClient("RelativeBinding_WMSQuery");
WMSQueryService.FeatureInfoParams fip = new WMSQueryService.FeatureInfoParams()
{
Url = WLyr.Url,
Extent = _Map.Extent,
Layers = string.Join(",", WLyr.Layers),
Map = new System.Windows.Rect(0, 0, _Map.Width, _Map.Height),
Point = new Point(_Map.MapToScreen(ptMapPoint).X, _Map.MapToScreen(ptMapPoint).Y),
SRID = _Map.SpatialReference.WKID,
Version = WLyr.Version
};
client.GetFeatureInfoAsync(fip);
... View more
08-04-2011
08:35 AM
|
0
|
3
|
1222
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 10-23-2017 08:59 AM | |
| 1 | 06-15-2016 03:27 PM | |
| 1 | 01-14-2016 09:55 AM | |
| 2 | 12-14-2012 09:38 AM | |
| 2 | 10-23-2017 01:22 PM |
| Online Status |
Offline
|
| Date Last Visited |
07-17-2024
08:14 PM
|