How do you get the proper mapping name from a binding source bound to a List<T>, or an anonymous type, to use on a DataGridTableStyle?

喜你入骨 提交于 2019-12-09 14:20:09

问题


I'm trying to create a DataGridTableStyle object so that I can control the column widths of a DataGrid. I've created a BindingSource object bound to a List. Actually it's bound to an anonymous type list created though Linq in the following manner (variable names changed for clarity of what I'm doing):

List<myType> myList = new List<myType>(someCapacity);
.
...populate the list with query from database...
.

var query = from i in myList
            select new
            {
                i.FieldA,
                i.FieldB,
                i.FieldC
            };

myBindingSource.DataSource = query;
myDataGrid.DataSource = myBindingSource;

Then I create a DataGridTableStyle object and add it to the datagrid. However, it never applies my table style properties I set up because I can't seem set the proper myDataGridTableStyle.MappingName property.

I've searched Google for about 1/2 an hour and keep seeing links to the same question throughout a bunch of different forums (literally the same text, like someone just copied and pasted the question... I hate that...). Anyway, none of the suggestions work, just like the guy says on all the other sites.

So does anybody here know what I need to set the MappingName property to in order to have my TableStyle actually work properly? Where can I grab the name from? (It can't be blank... that only works with a BindingSource that is bound to a DataTable or SqlCeResultSet etc.).

I'm thinking it could be an issue with me using Linq to create an anonymous, more specialized version of the objects with only the fields I need. Should I just try to bind the BindingSource directly to the List object? Or maybe even bind the DataGrid directly to the List object and skip the binding source altogether.

Thanks

PS - C#, Compact Framework v3.5

UPDATE:

I've posted an answer below that solved my problem. Whether or not it's the best approach, it did work. Worth a peek if you're having the same issue I had.


回答1:


I've found the way to make this work. I'll break it out into sections...


List<myType> myList = new List<myType>(someCapacity);
.
...populate the list with query from database...
.

DataGridTableStyle myDataGridTableStyle = new DatGridtTableStyle();
DataGridTextBoxColumn colA = new DataGridTextBoxColumn();
DataGridTextBoxColumn colB = new DataGridTextBoxColumn();
DataGridTextBoxColumn colC = new DataGridTextBoxColumn();

colA.MappingName = "FieldA";
colA.HeaderText = "Field A";
colA.Width = 50; // or whatever;

colB.MappingName = "FieldB";
.
... etc. (lather, rinse, repeat for each column I want)
.

myDataGridTableStyle.GridColumnStyles.Add(colA);
myDataGridTableStyle.GridColumnStyles.Add(colB);
myDataGridTableStyle.GridColumnStyles.Add(colC);

var query = from i in myList
            select new
            {
                i.FieldA,
                i.FieldB,
                i.FieldC
            };

myBindingSource.DataSource = query.ToList(); // Thanks Marc Gravell

// wasn't sure what else to pass in here, but null worked.
myDataGridTableStyle.MappingName = myBindingSource.GetListName(null); 

myDataGrid.TableStyles.Clear(); // Recommended on MSDN in the code examples.
myDataGrid.TablesStyles.Add(myDataGridTableStyle);
myDataGrid.DataSource = myBindingSource;

So basically, the DataGridTableStyle.MappingName needs to know what type of object it is mapping to. Since my object is an anonymous type (created with Linq), I don't know what it is until runtime. After I bind the list of the anonymous type to the binding source, I can use BindingSource.GetListName(null) to get the string representation of the anonymous type.

One thing to note. If I just bound the myList (which is type "myType") directly to the binding source, I could have just used the string "myType" as the value for DataGridTableStyle.MappingName.

Hopefully this is useful to other people!




回答2:


Just to add to the collection of answers already on this page....

I was just frustrated with this same issue trying to develop my fist application using windows forms and compact framework (For Windows Mobile 6.5).

What I found out, through Marc Gravell's comment above is that indeed is possible to get the run time MappingName inspecting the properties of the DataGrid. Doing this I found out that when binding my List<MyType> directly to the DataSource property of the DataGrid, the DataGrid was actually looking for a DataGridTableStyle with the MappingName of

"List`1"

instead of any combination of List<MyType> or MyType...

So... by putting "List`1" in the Mapping name on the DataGridTableStyle Collection Editor (at design time), I was able to customize the columns and other properties without having to create them all at run time.

I just hope this adds some more to the answers already provided. Thank you all for providing me with the guidelines.




回答3:


The query returns IEnumerable<T> for some T, but most binding sources (except ASP.NET) require IList (such as any IList<T> implementation) - try adding .ToList() - i.e.

myBindingSource.DataSource = query.ToList();

A BindingList<T> might work even better (if it is supported in CF 3.5) since it has better support for some of the common binding scenarios; if you need this (and assuming BindingList<T> exists on CF 3.5), you can add an extension method:

static BindingList<T> ToBindingList<T>(this IEnumerable<T> data)
{
    return new BindingList<T>(new List<T>(data));
}

then call:

myBindingSource.DataSource = query.ToBindingList();

For completeness, an alternative to an IList is IListSource (or even Type for purely-metadata scenarios), which is why DataSource is commonly typed as object; if it wasn't for this issue, the compiler probably would have been able to tell you the problem (i.e. if DataSource was defined as IList).




回答4:


I followed this answer and found that the MappingName always came out to be the underlying class name (myType in the example).

So it seems that putting the collection it through the BindingSource solves the problem anyway and that there is then no need for BindingSource.GetListName(null).

Also I found no need to ToList() the query as the BindingSource will also do this for you.

Many thanks to Jason Down for putting me on the right track.




回答5:


I was facing same problem for setting column width. After lot of R & D, i changed code as below and its working fine. Code:

DataGridTableStyle tableStyle = new DataGridTableStyle();
tableStyle.MappingName = dgCustom.DataSource.GetType().Name;

where dgCustom is DataGrid ID in dgCustom.DataSource.GetType().Name which is working perfectly.



来源:https://stackoverflow.com/questions/420386/how-do-you-get-the-proper-mapping-name-from-a-binding-source-bound-to-a-listt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!