I'm trying to bind a JSON array to a datagrid in Silverlight 3. I do not get any exceptions but I do not see the column values in the datagrid. I do see the rows though, but I do not know what the binding property should be. I do not want to create a class, populate the class and the bind. That works. I do not know what columns and datatypes the json string contains. I want the datagrid to just show all columns that are present in the json object.
Following is the code
Dim J As JsonArray = JsonArray.Load(New StringReader("[{'name':'arun', 'age':26, good:true},{'name':'kumar', 'age':28, good:false}]"))
For Each JJ In J
MessageBox.Show(JJ("name")) 'This shows the proper names'
Next
Dim c = New DataGridTextColumn()
c.Binding = New Binding("name")
GridUsers.Columns.Add(c)
GridUsers.ItemsSource = J
I do see 2 rows in the grid, but the columns values are always blank. What am I missing the binding property?
Many Thanks,
Arun
Have you tried JSON.NET? Version 3 apparently has support specifically for Silverlight 3:
http://james.newtonking.com/archive/2008/08/25/json-net-3-0-released.aspx
This looks similar to the problem of binding to dynamically created columns. See http://www.scottlogic.co.uk/blog/colin/2009/04/binding-a-silverlight-datagrid-to-dynamic-data-via-idictionary/]1. The secret is to make the entire object the binding source and use a value converter and a converter parameter to identify individual members.
Related
I want to be able to enter SQL into a textbox and display the results in a WPF Datagrid. I thought to start with an SqlDataReader, and set the datagrid's ItemsSource to the data reader:
using (var cmd = conn.CreateCommand()) {
cmd.CommandText = sql.Text;
sqlResults.ItemsSource = cmd.ExecuteReader();
}
but this fails with the following error: Invalid attempt to call FieldCount when reader is closed, which I understand to mean that by the time WPF gets around to reading the FieldCount property of the row object, the using block has already been exited.
So I tried using LINQ and ToList, to get something that would persist in memory:
sqlResults.ItemsSource = cmd.ExecuteReader().Cast<DbDataRecord>().ToList();
but this only displays the 'FieldCount' for each row, which is apparently the only property which DbDataRecord has.
Some solutions I have considered:
Bind to a DataTable instead of a DataReader? But I don't need editing capabilities.
Select each row into an in-memory data structure? What data structure could I use? I can't use anonymous types, because the names and types of the columns change based on the SQL statement. If I use List<object>, how will the datagrid know to generate columns for each object in the list?
Create a custom type descriptor? It seems like overkill.
But I feel the solution should be very simple and easy. Am I missing something basic here?
Maybe a DataTable is overkill but it does what you need it to do.
Well, yep, from what you've said, I would probably go with a struct containing properties that match the DB columns, and just fill that with the linq, so you can easily bind to it.
Working more with JavaScript, and wondering if you can find an equivalent to the Eval (which is suggested never to be used by the creator, btw :), and if that would help ...
I have a dynamically created DataGridView that has a valid DataSource with one row bound to it. However, it is returning me 0 when I am doing a rowcount on the DataGridView.
dgResult.DataSource = resultDt; // a datatable containing one row
flowLayoutPanel.Controls.Add(dgResult);
int rows = dgResult.Rows.Count; // returning 0 always!
Can someone please tell me where I may be going wrong here?
I found the issue. I was displaying the grid in a tabbed page that was not selected. Unless the grid is visible, it does not raise the rowadded event (which is weird!) durnig databinding. I selected the tab page before doing the databind, and the rowcount worked.
Use this code instead:
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = resultDt;
dgResult.DataSource = bindingSource;
flowLayoutPanel.Controls.Add(dgResult);
var c = dgResult.Rows.Count;
The binding source is what's responsible for syncing your data with the control. You want to use it, rather than trying to assign the table directly to the control.
I have a custom data structure that is pretty much a list of string arrays that I want to display in a (virtual) datagrid in WPF. All the examples of binding I have seen have been to objects with known properties such as a Colors object with a Blue and Red property.
My data is being populated from a SQL query and returns an unknown number of columns.
How can I bind to this type of structure?
(I don't want to use something like ObservableCollection for performance reasons: my data is going to be static so I don't need INotifyPropertyChanged)
See the following question: How to populate a WPF grid based on a 2-dimensional array
If you're only interested in displaying your 2d data then the answer from Jobi Joy will get it done using a Grid.
If you also want to be able to edit the data then you can use a control I created a while back for this purpose called DataGrid2D which subclasses DataGrid
To use it, just add a reference to DataGrid2DLibrary.dll, add this namespace
xmlns:dg2d="clr-namespace:DataGrid2DLibrary;assembly=DataGrid2DLibrary"
and then bind it to your List<string[]> like this
<dg2d:DataGrid2D ItemsSource2D="{Binding ListStringArrayProperty}"/>
DataGrid2D Library
DataGrid2D Source
I am trying to find out how to read the value of my WPF datagrid cells.
something along the lines of
String myString = myDataGrid.Cells[1][2].ToString();
the datagrid has been created in XAML and i have populated the datagrid with row data by using
reportGrid.Items.Add(new cbResultRow() { ... });
now I want to go back and read cell values in my datagrid.
I have seen some examples of reading data from a selected row or cell, by I don't have any selection (the user doesnt interact with the datagrid).
i have also seen code like
foreach(DataGridRow myrow in myDataGrid.Rows)
however the compiler says Rows is not a member of datagrid.
I have searched for several hours to try to find out how to do what I would have thought was a very simple thing!
please help,
Thanks,
will.
The WPF datagrid was built to bind to something like a DataTable. The majority of the time, you will modify the DataTable, and the Rows/Columns within the DataTable that is bound to the DataGrid.
The DataGrid itself is the Visual Element for the DataTable. Here is a pretty good tutorial on how to do this. To modify data within a loop would look something like this.
foreach(DataRow row in myTable.Rows)
{
row["ColumnTitle"] = 1;
}
This would simply make all the values in Column "ColumnTitle" equal to 1. To access a single cell it would look something like this.
myTable.Rows[0][0] = 1;
This would set the first cell in your DataTable to 1.
This might help someone else.
foreach (DataRowView row in dgLista.SelectedItems)
{
string text = row.Row.ItemArray[index].ToString();
}
Good luck!
Here's a summary of the solution.
Winform
Type: System.windows.Forms.DataGridView
// C#
foreach (DataGridViewRow row in dataGridView1.Rows)
{
//"Column1" = column name in DataGridView
string text = row.Cells["Column1"].value.ToString();
}
WPF equivalent
Type: DataGrid
// C#
foreach (DataRowView row in dataGrid.Items)
{
string text = row.Row.ItemArray[index].ToString();
}
I have a WinForms .NET datagrid whose data source is a List<cLineItem> called lines. cLineItem is very simple class with properties like units (int), description (string) and unit amount (float).
In code, i populate the list of lines and then set the data source:
dataGridView1.DataSource = lines;
This correctly populates the grid, however, even though each of the columns in the grid are set to Sortable, when you click a column header, it doesnt sort the rows.
Sorting in DataGridView doesn't work by default, unless your source explicitly supports sorting. You need to wrap your data source in a SortableBindingList. You can use the files PropertyComparer.cs and SortableBindingList.cs from this zip file and use it like this:
dataGridView1.DataSource = new SortableBindingList<cLineItem>(lines);