Select to view content in your preferred language

2.1 RC: Unable to put Behavior on Button in DataTemplate of Legend

682
6
12-08-2010 10:21 AM
KirkKuykendall
Deactivated User
I'm unable to put the Spatial Query button from the Graphics Action Behaviors sample onto the Datatemplate of the Legend from this sample.

Is this possible?

Cross posted: http://gis.stackexchange.com/questions/4199/how-to-use-button-with-behavior-in-silverlight-legend

Thanks, Kirk
0 Kudos
6 Replies
JenniferNery
Esri Regular Contributor
Why would you want to put behavior inside Legend's DataTemplate?  Did you want RedLine action per individual layer? I'm not sure if this is what you want to do but TargetName will not be resolved at this level.

Maybe what you need to do is put GraphicsActions next to the Legend control but not inside the Legend's Template?
0 Kudos
KirkKuykendall
Deactivated User
Hi Jennifer -

Thanks for the fast response.

I've got a map with many arcgisdynamicmapservicelayers in it.  I'd like to provide an easy method for users to select features on a specific (sub) layer.  I was hoping to bind to the Layer.Url and Layer.ID in the template.

Kirk
0 Kudos
JenniferNery
Esri Regular Contributor
How about a button that will enable Draw for SpatialQuery as in this example (http://help.arcgis.com/en/webapi/silverlight/2.1/samples/start.htm#SpatialQuery). The QueryTask URL will then come from the following values:
string baseURL = (((sender as Button).DataContext as ESRI.ArcGIS.Client.Toolkit.Primitives.LayerItemViewModel).Layer as ESRI.ArcGIS.Client.ArcGISDynamicMapServiceLayer).Url;
// "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer"
int id = ((sender as Button).DataContext as ESRI.ArcGIS.Client.Toolkit.Primitives.LayerItemViewModel).SubLayerID;
string url = string.Format("{0}/{1}", baseURL, id); //QueryTask URL when draw is complete


Or maybe use these values to set SpatialQueryAction URL?
You can get this SpatialQueryAction in code:
var t = System.Windows.Interactivity.Interaction.GetTriggers(SpatialQueryBtn)[0]; 
var spatialQueryAction = t.Actions[0] as ESRI.ArcGIS.Client.Actions.SpatialQueryAction;
spatialQueryAction.Url = url;


Also, note that the symbol you use will need to change based on the geometry type for that sublayer.
0 Kudos
KirkKuykendall
Deactivated User
Hi Jennifer -

Yes, I'm familiar with that sample.  The selection is hardwired for US States.

I'd like to allow the user to quickly choose which layer from within that mapservice he wants to select features from.

I'm already using the Legend.  I'd like to add a button next to each layer in the tree and bind the SpatialQueryAction to whatever layer the button is on.  This would allow the user to select things from that layer.  At the leaves of the legend tree I would also like to use the symbol item value in the where clause of the spatialqueryaction.

Thanks, Kirk
0 Kudos
JenniferNery
Esri Regular Contributor
You can still use SpatialQueryAction but put it outside the Legend's Template. Name the button that this action belongs to so you may retrieve and set the Trigger for this element (in Post# 4, 2nd code snippet).

In your Legend Template, add a button or checkbox that will allow you to select sub layer of interest. In its click or checked event, set the SpatialQueryAction Url so that the next time it is performed it would be for the this sub layer  (in Post# 4, 1st + 2nd code snippets). Url and Symbol properties should be updated depending on the selected sub layer and its geometry type.
0 Kudos
DominiqueBroux
Esri Frequent Contributor
Hi Kirk,

I tried to debug your code:
 
        <DataTemplate> 
            <StackPanel Orientation="Horizontal"> 
            <CheckBox Content="{Binding Label}" 
                    IsChecked="{Binding IsEnabled, Mode=TwoWay}" 
                    IsEnabled="{Binding IsInScaleRange}">                                 
                </CheckBox> 
                <Button Content="Select"> 
                    <i:Interaction.Triggers> 
                        <i:EventTrigger EventName="Click"> 
                            <esriBehaviors:SpatialQueryAction          
                                DrawMode="Rectangle"          
                                LayerID="MyGraphicsLayer"          
                                Url="http://hq-gis-01/ArcGIS/rest/services/WaterInfrastructure2/MapServer/15" 
                                Symbol="{StaticResource GraphicsLayerFillSymbol}"          
                                TargetName="MyMap" /> 
                        </i:EventTrigger> 
                    </i:Interaction.Triggers> 
                </Button> 
                <Slider Maximum="1" Value="{Binding Layer.Opacity, Mode=TwoWay}" Width="50" /> 
            </StackPanel> 
        </DataTemplate> 
 


and, as Jennifer mentionned, I confirm that the TargetName can't be resolved inside a datatemplate (and it's not a legend issue nor an ESRI issue). The TargetObject of the action is always null.

In complement to the solution by code given by Jennifer, you might also create your own action which would initialize the Url and the map.

Example of an action deriving fom SpatialQueryAction :
public class LegendSpatialQueryAction : SpatialQueryAction
{
    protected override void Invoke(object parameter)
    {
        var frameWorkElement = AssociatedObject as FrameworkElement;
        var layerItem = (frameWorkElement == null ? null : frameWorkElement.DataContext as LayerItemViewModel);
        var dynamicLayer = (layerItem == null ? null : layerItem.Layer as ArcGISDynamicMapServiceLayer);
        var map = TargetObject as Map;
 
        TargetObject = null; // reset in order to send OnTargetChanged
        if (dynamicLayer != null && map != null)
        {
            if (layerItem.LayerType.Contains("MapLayer")) { } // TODO : decide what to do when action is called on map service layer item
            Url = dynamicLayer.Url + "/" + layerItem.SubLayerID;
            TargetObject = map;
            base.Invoke(parameter);
        }
    }
}
and you can use it in Layer template this way:
<esri:Legend.LayerTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Content="{Binding Label}" 
                    IsChecked="{Binding IsEnabled, Mode=TwoWay}" 
                    IsEnabled="{Binding IsInScaleRange}" VerticalAlignment="Center">
</CheckBox>
<Button Content="Select" Click="Button_Click" Margin="5,0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click" >
<local:LegendSpatialQueryAction DrawMode="Rectangle" LayerID="MyGraphicsLayer"
                                    TargetObject="{Binding ElementName=MyMap}"
                                    Symbol="{StaticResource GraphicsLayerFillSymbol}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
 
</StackPanel>
</DataTemplate>
</esri:Legend.LayerTemplate>


Note that the action should also initialize the symbol depending on the geometry type of the layer, but this is not done in my sample.
0 Kudos