I 开发者_运维知识库have Linq results that I want to bind to a DataGrid
, so I can edit the results. Please advise on what I am doing wrong. The following is my C#
code:
var root = XElement.Parse(xmlText);
var elementsThatCanBeEmpty = new HashSet<XName>
{
XName.Get("Login"),
XName.Get("CustomerStreet2"),
XName.Get("PayeeStreet2"),
XName.Get("PayAsName"),
XName.Get("PayeeAccount")
};
var transactionList =
from transactions in root.Elements(XName.Get("Transactions")).Elements().AsEnumerable()
where transactions.Elements().Any
(
el =>
String.IsNullOrEmpty(el.Value) &&
!elementsThatCanBeEmpty.Contains(el.Name)
)
select transactions;
foreach (var t in transactionList)
{
Response.Write(t.Element(XName.Get("CustomerName")).Value);
}
dgBillPay.DataSource = transactionList;
dgBillPay.DataBind();
When I run the page, the DataGrid has headers of "Value
, Xml
, HasAttributes
, HasElements
, IsEmpty
, Value
, BaseUri
". What am I doing wrong here? Please advise.
Generally, databinding in asp.net controls works by inspecting the properties of the list of objects provided as the data source.
In this case, the datagrid has been set to auto generate columns, which means it will auto generate the headers based on the properties of the object(s) passed to it. Here you're passing an IEnumerable<XElement>
, so it's using its property list as the binding list.
Your options here are to:
- Use the select in your linq statement to create an anonymous type, and name the values appropriately as you go.
- Create a private class locally with the names you want the headers to be.
- Go old-school and use a DataTable. These are at least useful in that you can set column header names programmatically, as well as a long list of other 'features'.
- Set up your column names manually in the markup for your data bound control, override the ItemDataBound event and handle placing the correct data yourself. See the pages for BoundField and DataGrid.ItemDataBound.
Anonymous types are probably the path of least resistance here.
From the looks of the code; it appears that you're binding a collection of XmlElements to your DataGrid based off your LINQ query.
I think you might want something like this:
var transactionList =
from transactions in root.Elements(XName.Get("Transactions")).Elements().AsEnumerable()
where transactions.Elements().Any
(
el =>
String.IsNullOrEmpty(el.Value) &&
!elementsThatCanBeEmpty.Contains(el.Name)
)
select new { CustomerName = transactions.Element(XName.Get("CustomerName")).Value};
And then fill out the select part as you see fit.
I believe the problem you're seeing is because you've enumerated the query results before you bind them to your control.
foreach (var t in transactionList)
{
Response.Write(t.Element(XName.Get("CustomerName")).Value);
}
Once that statement is executed, I'm pretty sure that transactionList is unusable for anything else, unless the query is executed again.
The other thing to try is converting the transactionList query results to a list, by calling ToList() on the query.
Try these two things and see what happens.
精彩评论