How to bind a collection of ExpandoObjects to a Data Grid? - silverlight

I'm trying to read a table from an Excel file (.xls) and display it in a DataGrid. The table has unknown dimensions and each column has values of one unknown type (string, double or int).
I access the file via COM and put the table in a List<> of ExpandoObjects. When I set DataGrid.ItemSource to the List the Grid remains visually empty.
Explicitly defining columns and their data binding yields the runtime message that the application can't find the specified properties in the ExpandoObjects.
How can I display the table in the GridView? I work with Silverlight 5 RC and was hoping for a simple way to do it. At least simpler than the solutions I saw for Silverlight 2 and 3 so far.

If it's dynamic and it doesn't implement ICustomTypeProvider, in Silverlight 5 it will not bind. It's really unfortunate since we have dynamic databinding in WPF, and in the case that properties can be known (like Expando), even writing a CustomType that would work for any IDynamicMetaObject provider isn't difficult, not to mention they could have just added it for Expando, especially since it's sealed.
So the bottom line is that you need to write your own dynamic type implementing ICustomTypeProvider

I realized Vladimir Bodurov's solution works fine for me. I replaced the ExpandoObjects by Dictionaries and used Bodurov's class to transform the List into something the DataGrid can process.

Related

How to properly manage a dynamic table of data for gui

So I need to display a DataGrid in WPF. I'm using RadGridView from Telerik and Caliburn.Micro framework using the MVVM strategy.
In my presentation there are differing number of columns, X+2 to be exact as there is always a Label column and a Total column and then X number of others that hold a decimal number.
I do know the number at runtime before I create the classes I need so that could help.
So I'm currently considering a few methods of doing this but some of them have drawbacks so I would love if someone could point me towards a solution.
Create a ViewModel class for each row and for each Cell. The X number will be a collection and binding to it is problematic. I would need to customize the RadGridView itsefl to actually manage this.
Create a DataTable an the run and bind to it. I haven't managed to make this work and not sure if RadGridView actually supports DataTable. This will also not allow me to keep metadata for each cell, something I need to be easily able to update the cells because column + row aren't the only distinguishing keys I need.
Somehow dynamically create a object with x+2 properties to bind to.
Are there any solutions, guides or something out there to help me here?

bind datagrid to List<string[]> wpf

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

is data binding instead of loading data table in my own code a bad practice for a readonly data grid view?

I am using DevExpress GridView here, but I am guessing that the issue is relevant more broadly, at least in the WinForms world of data-driven apps.
At present I am usually doing data binding when displaying data freshly loaded from database and this is also a common practice in the code base I inherited. But, often enough I am unable to format (alter the text) the bound data using format strings, so I end up having to hide the poorly formatted columns, add unbound columns with similar names and dynamically populate them with formatted data from the hidden ones (the previous programmer did even worse, he routinely formatted inside stored procedures, ugh!). I get the nagging feeling that maybe this approach just sucks.
So I am thinking about an alternative - suppose I create my own FormattableGridView especially for the purpose of displaying readonly data. All columns will be unbound and populated dynamically from the data table, while preserving the same column names as the data table itself. If I want to format some columns, some rows or in a zig-zag fashion through the grid, I just do it directly dynamically, because the unbound grid can be messed with just as easily as a 2-dimensional array.
This might sound nice and good, but apparently data binding of grid views (most of which presumably are also readonly) is a pretty common thing. I find it mentioned online all the time. So, are there drawbacks that I am ignorant of to the pattern I delineated above that keep it from spreading? Or is the data binding in itself an unwise pattern in these cases whereas what I described is indeed the better way?
EDITED:
ok, so in part answering my own question, further research uncovers DevExpress CustomColumnDisplayText event apparently specifically intended for unrestricted formatting of databound grids. Perhaps similar events exist in gridview components from other similar frameworks. Ok, so maybe that indeed is the proper pattern, although the event-driven way of handling this issue feels a bit weird.
The grid publishes the GridView.CustomColumnDisplayText event which can be used to format wrongly formatted values. I think, that this is the best and easiest solution for this task.

WPF Combobox with auto-complete/auto-filter?

I am eager to find some solid (free, Open Source, or tutorial/example) code to make a WPF Combobox do autocomlete/autofilter as the user types. But everything I've tried so far has had some sort of problem...
A Reusable WPF Autocomplete TextBox came close, but I can't get it to work with more than one filter (more info here).
WPF autocomplete textbox/combobox doesn't work for me because it inherits from UserControl, and thus doesn't support the DataTemplates I need (for showing/selecting the value of one property for an object with multiple properties).
Automatically Filtering a ComboBox in WPF didn't work because it doesn't seem to ever find the EditableTextBox portion of the inherited ComboBox code (via (TextBox)base.GetTemplateChild("PART_EditableTextBox") which seems to always returns null).
Building a Filtered ComboBox for WPF just gets stuck in a refresh loop then overflows the stack after I type just a few letters.
Other things I've considered:
I know that Windows Forms' Combobox control has AutoCompleteMode and I could embed it in WPF, but I can't imagine it would play very well with my WPF data bindings.
Perhaps it is too complex and I need to simplify, maybe by building one-dimensional (single-property) ObservableCollections for the ComboBoxen... However, the challenge of applying multiple filters (one set by another control's value, and one from what the user is typing) to multiple controls using different views of the same DataSet would require a ridiculous amount of processing power to destroy and rebuild the list every time the user types a character!
So... I'm at wit's end. Any suggestions?
If your Combobox has some data source attached to it ,
just make
1-IsTextSearchEnabled = true.
2-IsEditable = true.
you are good to go
Try this one:
http://blogs.windowsclient.net/dragonz/archive/2010/02/23/autocomplete-textbox-control-for-wpf.aspx

Array binding Xaml by Position on Datagrid

I have a list of string array as input. The array dimension are static for all the list but I can't know the array size until the list is retrieved.
I need to bind the list in a datagrid in Silverlight.
I tried to create columns at runtime, binding each column to a particular array position but cannot find a way.
Have you any idea how to do it?
I could eventually "convert" my list of array in anything else that could be binded in a datagrid?
The idea is to have a sort of 2d Matrix showed inside the datagrid in Silverlight (I think that the problem is similar).
List
column_1 column_2 column_3 .. column_m
string[1,1] string[1,2] string[1,3] .. string[1,m]
string[2,1] string[2,2] string[2,3] .. string[2,m]
string[3,1] string[3,2] string[3,3] .. string[3,m]
....
string[n,1] string[n,2] string[n,3] .. string[n,m]
n is list lenght, m is list column max number.
Any idea is appreciated
I've found two solution to the problem that use the schema in the Denis's answer:
the first one is to use reflection to generate a class at runtime for the binding as suggested in this article (thanks to Vladimir Bodurov). I've tested this solution and I'll try to use it on my project. The only problem right now is that for large collection, the performance are poor. But I hope that someone will fix it in next relese (Silverlight 3 seems to not have fixed this problem, yet)
the second solution will be using some dynamic language for generate data. I don't know if this could be faster or not (probably not) but eventually could help. I will try in the future and use ironpython or ruby to generate classes that will be binded in datagrid.
If anyone have tryed using the second solution or any performance related information about creating classes at runtime, it will be appreciated.
Giorgio
Unfortunately that's not gonna be easy.
Do you have any valid constraints, like the maximum number of columns that is allowed or anything like that?
If you do (let's say you have N column maximum), you might be able to do something by
Having a class that exposes N
properties (named Col1...ColN for
example) that map the content
of the array for one line at column
X
Generating a list of that class,
one instance for each line
Generating the correct number of
column on the fly, binding each
column to property ColX
Binding your DataGrid to that list
That's kind of ugly, but it would work.
If you do not have to rely on the DataGrid, there is a possibility using a UniformGrid. A UniformGrid is a panel that layouts its children in a regular grid (every item has the same width, every item has the same height). You can indicate the number of columns at runtime, and the panel will fit children one after the other up to the number of columns and then continue on another line.
You could bind an ItemsControl to your array, indicating it should use a UniformGrid as its layout panel and indicating a suitable ItemTemplate to render each string.
The second option is much easier, but you will not have the capabilities of the DataGrid like sorting, moving columns, row selection, edition events per row etc.

Resources