views:

271

answers:

2

I am currently doing LINQ-to-XML and populating a DataGridView with my query just fine. The trouble I am running into is that once loaded into the DataGridView, the values appear to be Un-editable (ReadOnly). Here's my code:

var barcodes = (from src in xmldoc.Descendants("Container")
                where src.Descendants().Count() > 0
                select
                new
                {
                   Id = (string)src.Element("Id"),
                   Barcode = (string)src.Element("Barcode"),
                   Quantity = float.Parse((string)src.Element("Quantity").Attribute("value"))
                }).Distinct();

dataGridView1.DataSource = barcodes.ToList();

I read somewhere that the "DataGridView will be in ReadOnly mode when you use Anonymous types." But I couldn't find an explanation why or exactly what to do about it.

Any ideas?

EDIT -- Here's the answer I came up with...

So I added a "Container" class (with Get and Set <-- very important!) to avoid the Anonymous types being ReadOnly issue:

    public class Container
    {
        public string Id { get; set; }
        public string Barcode { get; set; }
        public float Quantity { get; set; }
    }

    // For use with the Distinct() operator
    public class ContainerComparer : IEqualityComparer<Container>
    {
        public bool Equals(Container x, Container y)
        {
            return x.Id == y.Id;
        }

        public int GetHashCode(Container obj)
        {
            return obj.Id.GetHashCode();
        }
    }

and changed the LINQ statement to:

var barcodes = (from src in xmldoc.Descendants("Container")
            where src.Descendants().Count() > 0
            select
            new Container
            {
               Id = (string)src.Element("Id"),
               Barcode = (string)src.Element("Barcode"),
               Quantity = float.Parse((string)src.Element("Quantity").Attribute("value"))
            }).Distinct(new ContainerComparer());

And that's it! Thanks for the help, Glenn!

+1  A: 

The reason that the data grid view is in ReadOnly mode when binding to anonymous types is that anonymous types are ReadOnly. You will get the same behaviour if you bind the view to a list of objects with only read only properties.

The only solution that I know of is to create a container for the data that is editable. A class with properties defining a get and set will give you what you are after.

Glenn Condron
@Glenn: Thanks. That kinda makes sense in my head. Though forgive me for being a LINQ newbie, but I'm still trying to wrap my head around what is going on under the hood. What's confusing to me is that it would seem that an Anonymous type would still return references to each value, such that when the value in a field of the DataGridView is altered, the XML data in the XDocument is simultaneously altered as well. So are you saying that if I create a class that can contain those values, that I'll be able to get what I'm seeking?
Pretzel
A: 

It's probably because of limitation in C# 3 - you can't use anonymous types as return types from methods. See for example this

Jacob Seleznev