照例让我们以源码开始
<Grid x:Name="LayoutRoot" Background="White">
<Grid.Resources>
<symbol:SimpleFillSymbol x:Key="DefaultFillSymbol" Fill="#01FFFFFF" BorderBrush="#88000000"
BorderThickness="2" />
<symbol:SimpleMarkerSymbol x:Key="DefaultMarkerSymbol" Color="Red" Size="6" Style="Diamond" />
</Grid.Resources>
<esri:Map x:Name="MyMap" WrapAround="True" Extent="-15000000,2000000,-7000000,8000000">
<esri:ArcGISTiledMapServiceLayer ID="BaseMapLayer"
Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
<esri:GraphicsLayer ID="CitiesGraphicsLayer">
<esri:GraphicsLayer.MapTip>
<Border BorderBrush="DarkGray" CornerRadius="13" BorderThickness="1" Margin="0,0,15,15">
<Border.Effect>
<DropShadowEffect ShadowDepth="10" BlurRadius="14" Direction="300" />
</Border.Effect>
<Border CornerRadius="10" Background="#DDFFEEEE" BorderThickness="5" BorderBrush="#77FF0000">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" Margin="10">
<StackPanel Orientation="Horizontal">
<TextBlock Text="City Name: " FontWeight="Bold" Foreground="#FF0F274E" FontSize="10" VerticalAlignment="Center"/>
<TextBlock Text="{Binding [CITY_NAME]}" HorizontalAlignment="Left" VerticalAlignment="Center" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Population: " FontWeight="Bold" Foreground="#FF0F274E" FontSize="10" VerticalAlignment="Center" />
<TextBlock Text="{Binding [POP1990]}" HorizontalAlignment="Left" VerticalAlignment="Center" />
</StackPanel>
</StackPanel>
</Border>
</Border>
</esri:GraphicsLayer.MapTip>
</esri:GraphicsLayer>
</esri:Map>
</Grid>
注意前端引入 xmlns:symbol="clr-namespace:ESRI.ArcGIS.Client.Symbols;assembly=ESRI.ArcGIS.Client"
后台:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
MyMap.PropertyChanged += MyMap_PropertyChanged;
}
void MyMap_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "SpatialReference")
{
CitiesGraphicsLayerLoad();
MyMap.PropertyChanged -= MyMap_PropertyChanged;
}
}
private void CitiesGraphicsLayerLoad()
{
ESRI.ArcGIS.Client.Tasks.Query query = new ESRI.ArcGIS.Client.Tasks.Query()
{
Geometry = new ESRI.ArcGIS.Client.Geometry.Envelope(-180, 0, 0, 90),
ReturnGeometry = true,
OutSpatialReference = MyMap.SpatialReference
};
query.OutFields.Add("*");
query.Where = "POP1990 > 100000";
QueryTask queryTask = new QueryTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer/0");
queryTask.ExecuteCompleted += CitiesGraphicsLayerQueryTask_ExecuteCompleted;
queryTask.ExecuteAsync(query);
}
void CitiesGraphicsLayerQueryTask_ExecuteCompleted(object sender, QueryEventArgs queryArgs)
{
if (queryArgs.FeatureSet == null)
return;
FeatureSet resultFeatureSet = queryArgs.FeatureSet;
ESRI.ArcGIS.Client.GraphicsLayer graphicsLayer =
MyMap.Layers["CitiesGraphicsLayer"] as ESRI.ArcGIS.Client.GraphicsLayer;
if (resultFeatureSet != null && resultFeatureSet.Features.Count > 0)
{
foreach (ESRI.ArcGIS.Client.Graphic graphicFeature in resultFeatureSet.Features)
{
graphicFeature.Symbol = LayoutRoot.Resources["DefaultMarkerSymbol"] as ESRI.ArcGIS.Client.Symbols.Symbol;
graphicsLayer.Graphics.Add(graphicFeature);
}
}
}
}
运行看看效果,然后我们再研究QueryTask的神秘。
QueryTask是一个进行空间和属性查询的功能类,它是针对某个地图服务的某个子图层进行查询(这个是与后面介绍FindTask的差别所在)。下面分别看看属性查询和空间查询的实例,其实MapTips的实现也是利用QueryTask查询属性。不妨再看一个查询属性应用:
<Grid x:Name="LayoutRoot" Background="White">
<Canvas x:Name="ResultsDisplayCanvas" HorizontalAlignment="Center" VerticalAlignment="Top" Width="547" Height="200" Margin="0,30,0,0" >
<Rectangle Stroke="Gray" RadiusX="10" RadiusY="10" Fill="#77919191" Canvas.Left="0" Canvas.Top="0" Width="547" Height="200" >
<Rectangle.Effect>
<DropShadowEffect/>
</Rectangle.Effect>
</Rectangle>
<Rectangle Fill="#FFFFFFFF" Stroke="DarkGray" RadiusX="5" RadiusY="5" Canvas.Left="10" Canvas.Top="20" Width="530" Height="170" />
<TextBlock x:Name="DataDisplayTitle" Text="Using Query tasks without maps" Foreground="White" FontSize="9" Canvas.Left="10" Canvas.Top="4" FontWeight="Bold" />
<StackPanel Orientation="Horizontal" Margin="5,0,15,0" Canvas.Top="25" >
<TextBlock Text="US State Name contains:" Margin="10,0,0,0" VerticalAlignment="Center"/>
<TextBox x:Name="StateNameTextBox" Text="New" Height="23" HorizontalAlignment="Left" VerticalAlignment="Center" Width="125" TextWrapping="NoWrap"
Margin="10,0,10,0" FontSize="12" Background="White" AcceptsReturn="False" />
<Button Content="Do Query" Width="75" VerticalAlignment="Center" HorizontalAlignment="Right" Click="QueryButton_Click" Margin="0,0,10,0" Cursor="Hand" />
</StackPanel>
<slData:DataGrid x:Name="QueryDetailsDataGrid" AutoGenerateColumns="False" HeadersVisibility="Column" Background="White"
IsReadOnly="True" Canvas.Left="10" Canvas.Top="50" Height="140" Width="530"
HorizontalScrollBarVisibility="Hidden">
<slData:DataGrid.Columns>
<slData:DataGridTextColumn Width="85" Binding="{Binding Attributes[STATE_NAME]}" Header="State Name"/>
<slData:DataGridTextColumn Width="110" Binding="{Binding Attributes[SUB_REGION] }" Header="Region"/>
<slData:DataGridTextColumn Width="45" Binding="{Binding Attributes[STATE_FIPS] }" Header="FIPS"/>
<slData:DataGridTextColumn Width="85" Binding="{Binding Attributes[STATE_ABBR] }" Header="Abbreviation"/>
<slData:DataGridTextColumn Width="103" Binding="{Binding Attributes[POP2000] }" Header="Population 2000"/>
<slData:DataGridTextColumn Width="102" Binding="{Binding Attributes[POP2007] }" Header="Population 2007"/>
</slData:DataGrid.Columns>
</slData:DataGrid>
</Canvas>
</Grid>
public partial class QueryWithoutMap : UserControl
{
public QueryWithoutMap()
{
InitializeComponent();
}
void QueryButton_Click(object sender, RoutedEventArgs e)
{
QueryTask queryTask =
new QueryTask("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/5");
queryTask.ExecuteCompleted += QueryTask_ExecuteCompleted;
queryTask.Failed += QueryTask_Failed;
ESRI.ArcGIS.Client.Tasks.Query query = new ESRI.ArcGIS.Client.Tasks.Query();
query.Text = StateNameTextBox.Text;
query.OutFields.Add("*");
queryTask.ExecuteAsync(query);
}
void QueryTask_ExecuteCompleted(object sender, ESRI.ArcGIS.Client.Tasks.QueryEventArgs args)
{
FeatureSet featureSet = args.FeatureSet;
if (featureSet != null && featureSet.Features.Count > 0)
QueryDetailsDataGrid.ItemsSource = featureSet.Features;
else
MessageBox.Show("No features returned from query");
}
private void QueryTask_Failed(object sender, TaskFailedEventArgs args)
{
MessageBox.Show("Query execute error: " + args.Error);
}
}
这段代码中注意 query.Text = StateNameTextBox.Text;和 query.OutFields.Add("*")。query.Text值对应Url中的子图层的显示字段,也就是在Url中图层的显示字段中模糊查找query.Text。直接访问Uri会看到Display Field: STATE_NAME,这样就等同另种写法query.Where = "STATE_NAME like '%" + StateNameTextBox.Text + "%'";
query.OutFields.Add("*")表示返回所有属性字段。
下面看一个QueryTask查询空间的实例:
<Grid x:Name="LayoutRoot" Background="White">
<Grid.Resources>
<Style x:Key="MyCustomRow" TargetType="slData:DataGridRow">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="slData:DataGridRow">
<slPrimitives:DataGridFrozenGrid Name="Root">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0" />
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal" >
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To=".5"/>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#ebf4fa"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal AlternatingRow">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="0"/>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#bbd9ee"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To=".5"/>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#8800FFFF"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal Selected">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#8800FFFF"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver Selected">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#8800FFFF"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused Selected">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>
<ColorAnimationUsingKeyFrames BeginTime="0" Duration="0" Storyboard.TargetName="BackgroundRectangle" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="0" Value="#8800FFFF"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.Resources>
<Storyboard x:Key="DetailsVisibleTransition">
<DoubleAnimation Storyboard.TargetName="DetailsPresenter" Storyboard.TargetProperty="ContentHeight"
Duration="00:00:0.1" />
</Storyboard>
</Grid.Resources>
<Rectangle x:Name="BackgroundRectangle" Grid.RowSpan="2" Grid.ColumnSpan="2" Opacity="0"
Fill="#FFFFCC00"/>
<slPrimitives:DataGridRowHeader Grid.RowSpan="3" Name="RowHeader"
slPrimitives:DataGridFrozenGrid.IsFrozen="True" />
<slPrimitives:DataGridCellsPresenter Grid.Column="1" Name="CellsPresenter"
slPrimitives:DataGridFrozenGrid.IsFrozen="True" />
<slPrimitives:DataGridDetailsPresenter Grid.Row="1" Grid.Column="1" Name="DetailsPresenter" />
<Rectangle Grid.Row="2" Grid.Column="1" Name="BottomGridLine" HorizontalAlignment="Stretch"
Height="1" />
</slPrimitives:DataGridFrozenGrid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<symbol:SimpleMarkerSymbol x:Key="DefaultMarkerSymbol" Color="Red" Size="12" Style="Circle" />
<symbol:SimpleLineSymbol x:Key="DefaultLineSymbol" Color="Red" Width="4" />
<symbol:FillSymbol x:Key="DefaultFillSymbol" >
<symbol:FillSymbol.ControlTemplate>
<ControlTemplate>
<Path x:Name="Element" IsHitTestVisible="False" Fill="#66FF0000"
Stroke="Red" StrokeThickness="1"/>
</ControlTemplate>
</symbol:FillSymbol.ControlTemplate>
</symbol:FillSymbol>
<symbol:FillSymbol x:Key="ResultsFillSymbol">
<symbol:FillSymbol.ControlTemplate>
<ControlTemplate x:Name="CustomPolygonTemplate">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ColorAnimation Storyboard.TargetName="Element"
Storyboard.TargetProperty="(Fill).(Color)"
To="#880000FF" Duration="0:0:0.1" />
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Storyboard.TargetName="Element"
Storyboard.TargetProperty="(Fill).(Color)"
To="#8800FFFF" Duration="0:0:0.1" />
</Storyboard>
</VisualState>
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimation Storyboard.TargetName="Element"
Storyboard.TargetProperty="(Fill).(Color)"
To="#8800FFFF" Duration="0:0:0.1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Path x:Name="Element" Stroke="Blue" Fill="#880000FF"
StrokeStartLineCap="Round" StrokeThickness="2"
StrokeLineJoin="Round" StrokeEndLineCap="Round" />
</Grid>
</ControlTemplate>
</symbol:FillSymbol.ControlTemplate>
</symbol:FillSymbol>
</Grid.Resources>
<esri:Map x:Name="MyMap" WrapAround="True" Extent="-15000000,2000000,-7000000,8000000">
<esri:ArcGISTiledMapServiceLayer ID="StreetMapLayer"
Url=">
<esri:GraphicsLayer ID="MySelectionGraphicsLayer" />
</esri:Map>
</Grid>
注意引入xmlns:slPrimitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Data"
后台:
public partial class MainPage : UserControl
{
private Draw MyDrawSurface;
public MainPage()
{
InitializeComponent();
MyDrawSurface = new Draw(MyMap)
{
LineSymbol = LayoutRoot.Resources["DefaultLineSymbol"] as SimpleLineSymbol,
FillSymbol = LayoutRoot.Resources["DefaultFillSymbol"] as FillSymbol
};
MyDrawSurface.DrawComplete += MyDrawSurface_DrawComplete;
MyDrawSurface.DrawMode = DrawMode.Point;
MyDrawSurface.IsEnabled = true;
}
private void MyDrawSurface_DrawComplete(object sender, ESRI.ArcGIS.Client.DrawEventArgs args)
{
GraphicsLayer selectionGraphicslayer = MyMap.Layers["MySelectionGraphicsLayer"] as GraphicsLayer;
selectionGraphicslayer.ClearGraphics();
QueryTask queryTask = new QueryTask("
http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/5");queryTask.ExecuteCompleted += QueryTask_ExecuteCompleted;
queryTask.Failed += QueryTask_Failed;
// Bind data grid to query results
Binding resultFeaturesBinding = new Binding("LastResult.Features");
resultFeaturesBinding.Source = queryTask;
Query query = new ESRI.ArcGIS.Client.Tasks.Query();
// Specify fields to return from query
query.OutFields.AddRange(new string[] { "STATE_NAME", "SUB_REGION", "STATE_FIPS", "STATE_ABBR", "POP2000", "POP2007" });
query.Geometry = args.Geometry;
// Return geometry with result features
query.ReturnGeometry = true;
query.OutSpatialReference = MyMap.SpatialReference;
queryTask.ExecuteAsync(query);
}
private void QueryTask_ExecuteCompleted(object sender, ESRI.ArcGIS.Client.Tasks.QueryEventArgs args)
{
FeatureSet featureSet = args.FeatureSet;
if (featureSet == null || featureSet.Features.Count < 1)
{
MessageBox.Show("No features retured from query");
return;
}
GraphicsLayer graphicsLayer = MyMap.Layers["MySelectionGraphicsLayer"] as GraphicsLayer;
if (featureSet != null && featureSet.Features.Count > 0)
{
foreach (Graphic feature in featureSet.Features)
{
feature.Symbol = LayoutRoot.Resources["ResultsFillSymbol"] as FillSymbol;
graphicsLayer.Graphics.Insert(0, feature);
}
}
MyDrawSurface.IsEnabled = true;
//MyDrawSurface.IsEnabled = (MyDrawSurface.DrawMode != DrawMode.None);
}
private void QueryTask_Failed(object sender, TaskFailedEventArgs args)
{
MessageBox.Show("Query failed: " + args.Error);
}
private void QueryDetailsDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (Graphic g in e.AddedItems)
g.Select();
foreach (Graphic g in e.RemovedItems)
g.UnSelect();
}
}
运行,在地图上单击。
这个实例相信大家先运行操作之后,再简单看看代码就会明白,在这我不解释,另外如果我们再往深处想一下,可以利用这点进行缓冲区的查询。
最后总之,大家记住进行空间和属性查询就是QueryTask的主要应用。后面我们再介绍FindTask和IdentifyTask两个常用的功能类。