Select to view content in your preferred language

Can I bind a 2D array to a dagagrid?

4111
8
06-15-2011 12:37 PM
DanDong
Deactivated User
Hi everyone,

In my application, spatial query task will perform on multiple layers (for example 6 layers) in one map service. So I want to define a 2D string array with row representing layer name and column representing hit result.

If the first query task performed on layer1 returns a no_null result and the second query task performed on layer2 returns null result, the first row in this 2D array would be like this:

Wetland    Resource found.
River        Resource not found.

Then I want to use a datagrid to display the results. So can I bind this 2D array to the datagrid? Thank you:)
0 Kudos
8 Replies
IgressT
Emerging Contributor
Hi everyone,

In my application, spatial query task will perform on multiple layers (for example 6 layers) in one map service. So I want to define a 2D string array with row representing layer name and column representing hit result.

If the first query task performed on layer1 returns a no_null result and the second query task performed on layer2 returns null result, the first row in this 2D array would be like this:

Wetland    Resource found.
River        Resource not found.

Then I want to use a datagrid to display the results. So can I bind this 2D array to the datagrid? Thank you:)


Yes you can... you can do something like this

            IDictionary<string, string> y = new Dictionary<string, string>();
            y.Add(new KeyValuePair<string, string>("Wetland", "Resource found."));
            y.Add(new KeyValuePair<string, string>("River", "Resource not found."));
            this.testGrid.ItemsSource = y;
0 Kudos
DanDong
Deactivated User
Hey Doc,

Thank you for the prompt reply. I have such datagrid in the xaml:
<slData:DataGrid x:Name="WirtReportDataGrid" Width="Auto" AutoGenerateColumns="False" HeadersVisibility="Column" Background="White" 
                             IsReadOnly="False" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Auto" Grid.Row="1"
                             CanUserSortColumns="True">
            <slData:DataGrid.Columns>
<slData:DataGridTextColumn Header="Critical Resource"/>
<slData:DataGridTextColumn Header="Resource in Vicinity of Project Polygon"/>
           </slData:DataGrid.Columns>
</slData:DataGrid>


'Critical Resource' refers to the layer's name, like wetland, river.
'Resource in Vicinity of Project Polygon' refers to 'found' or 'not found'.

I wrote below in cs file and it doesn't return any results in the datagrid.
private void WirtQueryTask_ExecuteCompleted(object sender, ESRI.ArcGIS.Client.Tasks.QueryEventArgs args)
        {

            FeatureSet featureSet = args.FeatureSet;
            string url ="";
            if (wirtMapLayer.Count != 0)
               url = wirtMapLayer.Peek();

            if (featureSet == null || featureSet.Features.Count < 1)
            {
                wirtReport.Add(new KeyValuePair<string, string>(url, "NO RESOURCE FOUND"));
            }

            else if (featureSet != null && featureSet.Features.Count > 0)
            {
                wirtReport.Add(new KeyValuePair<string, string>(url, "FOUND"));
            }

 wirtReportPage.WirtReportDataGrid.ItemsSource = wirtReport;
}


So If I use your method, do I need to also set any binding on the columns in xaml?
0 Kudos
IgressT
Emerging Contributor
Hey Doc, 

Thank you for the prompt reply. I have such datagrid in the xaml: 
<slData:DataGrid x:Name="WirtReportDataGrid" Width="Auto" AutoGenerateColumns="False" HeadersVisibility="Column" Background="White" 
                             IsReadOnly="False" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Auto" Grid.Row="1"
                             CanUserSortColumns="True">
            <slData:DataGrid.Columns>
<slData:DataGridTextColumn Header="Critical Resource"/>
<slData:DataGridTextColumn Header="Resource in Vicinity of Project Polygon"/>
           </slData:DataGrid.Columns>
</slData:DataGrid>


'Critical Resource' refers to the layer's name, like wetland, river. 
'Resource in Vicinity of Project Polygon' refers to 'found' or 'not found'. 

I wrote below in cs file and it doesn't return any results in the datagrid. 
private void WirtQueryTask_ExecuteCompleted(object sender, ESRI.ArcGIS.Client.Tasks.QueryEventArgs args)
        {

            FeatureSet featureSet = args.FeatureSet;
            string url ="";
            if (wirtMapLayer.Count != 0)
               url = wirtMapLayer.Peek();

            if (featureSet == null || featureSet.Features.Count < 1)
            {
                wirtReport.Add(new KeyValuePair<string, string>(url, "NO RESOURCE FOUND"));
            }

            else if (featureSet != null && featureSet.Features.Count > 0)
            {
                wirtReport.Add(new KeyValuePair<string, string>(url, "FOUND"));
            }

 wirtReportPage.WirtReportDataGrid.ItemsSource = wirtReport;
}


So If I use your method, do I need to also set any binding on the columns in xaml?


Try AutoGenerateColumns="True" in the XAML


<slData:DataGrid x:Name="WirtReportDataGrid" Width="Auto" AutoGenerateColumns="False" HeadersVisibility="Column" Background="White" 
                             IsReadOnly="False" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Auto" Grid.Row="1"
                             CanUserSortColumns="True">
            <slData:DataGrid.Columns>
<slData:DataGridTextColumn Header="Critical Resource"/>
<slData:DataGridTextColumn Header="Resource in Vicinity of Project Polygon"/>
           </slData:DataGrid.Columns>
</slData:DataGrid>
0 Kudos
IgressT
Emerging Contributor
Try as highlighted in red... it worked for me

Hey Doc, 

Thank you for the prompt reply. I have such datagrid in the xaml: 
<slData:DataGrid x:Name="WirtReportDataGrid" Width="Auto" AutoGenerateColumns="False" HeadersVisibility="Column" Background="White" 
                             IsReadOnly="False" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Auto" Grid.Row="1"
                             CanUserSortColumns="True">
            <slData:DataGrid.Columns>
<slData:DataGridTextColumn Header="Critical Resource" Binding="{Binding Key}"/>
<slData:DataGridTextColumn Header="Resource in Vicinity of Project Polygon" Binding="{Binding Value}"/>
           </slData:DataGrid.Columns>
</slData:DataGrid>


'Critical Resource' refers to the layer's name, like wetland, river. 
'Resource in Vicinity of Project Polygon' refers to 'found' or 'not found'. 

I wrote below in cs file and it doesn't return any results in the datagrid. 
private void WirtQueryTask_ExecuteCompleted(object sender, ESRI.ArcGIS.Client.Tasks.QueryEventArgs args)
        {

            FeatureSet featureSet = args.FeatureSet;
            string url ="";
            if (wirtMapLayer.Count != 0)
               url = wirtMapLayer.Peek();

            if (featureSet == null || featureSet.Features.Count < 1)
            {
                wirtReport.Add(new KeyValuePair<string, string>(url, "NO RESOURCE FOUND"));
            }

            else if (featureSet != null && featureSet.Features.Count > 0)
            {
                wirtReport.Add(new KeyValuePair<string, string>(url, "FOUND"));
            }

 wirtReportPage.WirtReportDataGrid.ItemsSource = wirtReport;
}


So If I use your method, do I need to also set any binding on the columns in xaml?
0 Kudos
DanDong
Deactivated User
Try as highlighted in red... it worked for me


Hey Doc, that works perfectly! Thank you so much!
I still have one question to consult: I have another two columns in the datagrid, like below, and
'Resource within Buffer' refers to 'found' or 'not found'
'Notes' refers to some notice word.

<slData:DataGridTextColumn Header="Resource within Buffer"/>
<slData:DataGridTextColumn Header="Notes"/>


So can I add more values within the same key and bind the other two values to the above columns? I saw new KeyValuePair only handle a key-value pair. Thanks a lot!!
wirtReport.Add(new KeyValuePair<string, string>(url, "RESOURCE FOUND"));
0 Kudos
IgressT
Emerging Contributor
You can still use a dictionary but something like this...

Open up AssemblyInfo.cs (it can be found under Properties folder) and add this line
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Windows")]
You have to this if you want to bind with anonymous types which I used in my code... do a google to find out why... anyways...

MainPage.xaml.cs
public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            IDictionary<string, object> y = new Dictionary<string, object>();
            y.Add("URL1", new {
                Prop1 = "A1",
                Prop2 = "A2",
                Prop3 = "A3"
            });
            y.Add("URL2", new {
                Prop1 = "B1",
                Prop2 = "B2",
                Prop3 = "B3"
            });
            y.Add("URL3", new {
                Prop1 = "C1",
                Prop2 = "C2",
                Prop3 = "C3"
            });            
            this.testGrid.ItemsSource = y;
        }
}


MainPage.xaml
<sdk:DataGrid AutoGenerateColumns="False"
                      Height="128"
                      HorizontalAlignment="Left"
                      Margin="18,43,0,0"
                      Name="testGrid"
                      VerticalAlignment="Top"
                      Width="370">
            <sdk:DataGrid.Columns>
                <sdk:DataGridTextColumn Header="Critical Resource"
                                        Binding="{Binding Key}" />
                <sdk:DataGridTextColumn Header="Resource in Vicinity of Project Polygon"
                                        Binding="{Binding Value.Prop1}" />
                <sdk:DataGridTextColumn Header="Resource within Buffer"
                                        Binding="{Binding Value.Prop2}" />
                <sdk:DataGridTextColumn Header="Notes"
                                        Binding="{Binding Value.Prop3}" />
            </sdk:DataGrid.Columns>
</sdk:DataGrid>
0 Kudos
DanDong
Deactivated User
Thanks a lot Doc! This really helps me out! 😄 And it is very useful for my future development. 🙂 Thanks again.
0 Kudos
DanDong
Deactivated User
Hey Doc, I encourted another issue with this method. The case is: For the first time, the method works very well. But after the user closes the datagrid, restarts some work and wants to show the datagrid again, I got an exception: An item with the same key has already been added

I define this IDictionary in public partial clas
IDictionary<string, object> wirtReport = new Dictionary<string, object>();


I tried to clear the IDictionary after the user restarts working
wirtReport.Clear();

But I still get the same exception.

The red color words are where I get the exception, it seems like it doesn't allow me to add a new item into the IDictionary, but I do clear it before going into this place. I am very frustrated.
for (int i = 0; i < wirtlayerlist.Count; i++)
            {
                if (wirtlayerlist.ElementAt(i) == 18)
                    wirtReport.Add(wirtResult[0, 0], new { Prop1 = wirtResult[0, 1], Prop2 = wirtResult[0, 2], Prop3 = wirtResult[0, 3] });
                else if (wirtlayerlist.ElementAt(i) == 21)
                    wirtReport.Add(wirtResult[1, 0], new { Prop1 = wirtResult[1, 1], Prop2 = wirtResult[1, 2], Prop3 = wirtResult[1, 3] });
                else if (wirtlayerlist.ElementAt(i) == 20)
                    wirtReport.Add(wirtResult[2, 0], new { Prop1 = wirtResult[2, 1], Prop2 = wirtResult[2, 2], Prop3 = wirtResult[2, 3] });
                else if (wirtlayerlist.ElementAt(i) == 23)
                    wirtReport.Add(wirtResult[3, 0], new { Prop1 = wirtResult[3, 1], Prop2 = wirtResult[3, 2], Prop3 = wirtResult[3, 3] });
                else if (wirtlayerlist.ElementAt(i) == 16)
                    wirtReport.Add(wirtResult[4, 0], new { Prop1 = wirtResult[4, 1], Prop2 = wirtResult[4, 2], Prop3 = wirtResult[4, 3] });
                else if (wirtlayerlist.ElementAt(i) == 14)
                    wirtReport.Add(wirtResult[5, 0], new { Prop1 = wirtResult[5, 1], Prop2 = wirtResult[5, 2], Prop3 = wirtResult[5, 3] });
            }

            wirtReportPage.WirtReportDataGrid.ItemsSource = wirtReport;
            wirtReportPage.ParentLayoutRoot = InfoStackPanel;
            wirtReportPage.thisPass(this);
            wirtReportPage.Show();  


Do you have some ideas or clues on how to solve this problem? Thank you!!
0 Kudos