<Border x:Name="CountyResultsDisplay" Background="#77919191" BorderThickness="1" CornerRadius="5" HorizontalAlignment="Center" VerticalAlignment="Top" Visibility="Collapsed" Margin="5" Padding="10" BorderBrush="Black"> <Border.Effect> <DropShadowEffect/> </Border.Effect> <Grid> <Grid.RowDefinitions> <RowDefinition Height="15" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <TextBlock x:Name="DataDisplayTitle" Text="Search Results" Foreground="Black" FontSize="9" Grid.Row="0" FontWeight="Bold" /> <slData:DataGrid x:Name="QueryDetailsDataGrid" Grid.Row="1" Width="Auto" Height="170" AutoGenerateColumns="False" HeadersVisibility="Column" Background="White" IsReadOnly="True" HorizontalScrollBarVisibility="Hidden" RowStyle="{StaticResource MyCustomRow}" CanUserSortColumns="True" SelectionChanged="QueryDetailsDataGrid_SelectionChanged" LoadingRow="QueryDetailsDataGrid_LoadingRow"> <slData:DataGrid.Columns> <slData:DataGridTextColumn CanUserSort="True" SortMemberPath="NAME_CNTY" Binding="{Binding Attributes[OBJECTID]}" Header="Rec"/> <slData:DataGridTextColumn CanUserSort="False" Binding="{Binding Attributes[NAME_CNTY]}" Header="County Name"/> <slData:DataGridTextColumn CanUserSort="False" Binding="{Binding Attributes[AREA_SQMI]}" Header="Area"/> <slData:DataGridTextColumn CanUserSort="False" Binding="{Binding Attributes[POP_1990]}" Header="Population 1997"/> <slData:DataGridTextColumn CanUserSort="False" Binding="{Binding Attributes[POP_2000]}" Header="Population 2000"/> <slData:DataGridTextColumn CanUserSort="True" SortMemberPath="POP2007" Binding="{Binding Attributes[FIPS_CNTY]}" Header="FIPS"/> </slData:DataGrid.Columns> </slData:DataGrid> </Grid> </Border>
Query query = new ESRI.ArcGIS.Client.Tasks.Query(); //bind data grid to query results Binding resultFeaturesBinding = new Binding("LastResult.Features"); resultFeaturesBinding.Source = queryTask; // Specify fields to return from query according to different layers if (selectlayerid == 9) { DataGrid dg = rectangleselection.QueryDetailsDataGrid; List <string> Colnames = new List <string> {"OBJECTID", "NAME", "AREA_SQMI", "POP_1990", "POP_2000", "FIPS_CNTY"} ; //header name of the column dg.Columns.Clear(); if (dg != null) { if (Colnames != null && Colnames.Count > 0) foreach (string col in Colnames) { DataGridTextColumn dataGridTextColumn = new DataGridTextColumn(); Binding binder = new Binding(); //you can use the converter if you are binding IDictionary to the datagrid //binder.Converter = new AttributeRowIndexConverter(); // binder.ConverterParameter = col; binder.Path = new PropertyPath("Attributes"); dataGridTextColumn.Header = col; binder.Mode = BindingMode.OneWay; dataGridTextColumn.Binding = binder; dg.Columns.Add(dataGridTextColumn); } } rectangleselection.QueryDetailsDataGrid.SetBinding(DataGrid.ItemsSourceProperty, resultFeaturesBinding); query.OutFields.AddRange(new string[] { "OBJECTID", "NAME_CNTY", "AREA_SQMI", "POP_1990", "POP_2000", "FIPS_CNTY" }); }
You have to bind to a specific attribbute not to the whole dictionary (e.g. in XAML Binding="{Binding Attributes[NAME_CNTY]}" ).
So instead of 'binder.Path = new PropertyPath("Attributes");', try with : binder.Path = new PropertyPath("Attributes[" + col + "]");
Can I bind the visible attribute fields in each layer without specify the attribute names in codes. I mean I can set the attribute field of the layer to be visible or invisible in arcmap (please see the attached picture).
If I want the query task returns the results from these visible attribute fields and I don't specify these attribute names in my code. Is there a way to do such thing?
So I am wondering if there is a way to read the visible columns automatically and only bind the visible columns and perform spatial query based on them.
string fieldname = featureSet.FieldAliases.ElementAt(i).ToString(); MessageBox.Show(fieldname);
private void SelectQueryTask_ExecuteCompleted(object sender, ESRI.ArcGIS.Client.Tasks.QueryEventArgs args) { FeatureSet featureSet = args.FeatureSet; if (featureSet != null && featureSet.Features.Count > 0) { switch (Convert.ToInt16(args.UserState.ToString())) { case 9: //specify the layerid { DataGrid dg = rectangleselection.QueryDetailsDataGrid; dg.Columns.Clear(); List<string> fields = new List<string>(); MessageBox.Show(featureSet.FieldAliases.Count().ToString()); foreach (var item in featureSet.FieldAliases) { DataGridTextColumn dataGridTextColumn = new DataGridTextColumn(); Binding binder = new Binding(); fields.Add(item.Value); binder.Path = new PropertyPath("Attributes[" + item.Value + "]"); dataGridTextColumn.Header = item.Value; binder.Mode = BindingMode.OneWay; dataGridTextColumn.Binding = binder; dg.Columns.Add(dataGridTextColumn); } rectangleselection.ParentLayoutRoot = InfoCanvas; rectangleselection.ResultsDisplay.Visibility = System.Windows.Visibility.Visible; rectangleselection.Show(); rectangleselection.thisPass(this); //pass current reference to rectangleselection break; }
I check the field alias from arcmap, for example, the field NAME_CNTY's field alias is NAME_CNTY, but when I use this line to display it, it shows [NAME_CNTY, NAME_CNTY]
Code:
string fieldname = featureSet.FieldAliases.ElementAt(i).ToString();MessageBox.Show(fieldname);
I don't know why it shows the duplicated name
binder.Path = new PropertyPath("Attributes[" + item.Value + "]");
The second question which is more confusing is that since I want to generate the column automatically I set the AutoGenerateColumns="True" for the datagrid according to Yamunadevi's advice
DataGrid dg = rectangleselection.QueryDetailsDataGrid; List<string> fields = new List<string>(); dg.Columns.Clear(); //generate the index column DataGridTextColumn dataGridTextColumnRec = new DataGridTextColumn(); Binding Recbinder = new Binding(); //Recbinder.Path = new PropertyPath(); dataGridTextColumnRec.Header = "Rec"; Recbinder.Mode = BindingMode.OneWay; dataGridTextColumnRec.Binding = Recbinder; dg.Columns.Add(dataGridTextColumnRec); foreach (var item in featureSet.FieldAliases) { DataGridTextColumn dataGridTextColumn = new DataGridTextColumn(); Binding binder = new Binding(); fields.Add(item.Value); //FieldAliases is a Dictionary, the field name being the key and the field alias being the value. binder.Path = new PropertyPath("Attributes[" + item.Key + "]"); dataGridTextColumn.Header = item.Value; binder.Mode = BindingMode.OneWay; dataGridTextColumn.Binding = binder; dg.Columns.Add(dataGridTextColumn); }
So if I change the field alias to something more common, e.g. Name (instead of the current NAME_CNTY), I should be able to use it by item.Value as the header of the column right?
I also try to add a new column as the index of the records, which should be the first column. I attach a scrrenshot hereAttachment 6498. So I generate a column before the fieldaliases loop. But I dont know how to give the Recbinder.Path since it is not an attribute of the featureset.
int rec = 0; foreach(var feature in featureSet.Features) feature.Attributes["Rec"] = ++rec;
Binding Recbinder = new Binding("Attributes[Rec]"); dataGridTextColumnRec.Header = "Rec"; Recbinder.Mode = BindingMode.OneWay; dataGridTextColumnRec.Binding = Recbinder; dg.Columns.Add(dataGridTextColumnRec);