0

I have a ListView (in WPF app) which I fill it programmatically:

l1.Items.Add(new
{
    AA = aa++,
    Description = descriptions[k],
    Shop = names[k + 2],
    Price = price
});

I want to take the first row and the value of column price. I can take the object

object b = l1.Items.GetItemAt(0);

but I can't take the price.

Tamir
  • 3,833
  • 3
  • 32
  • 41
user1005633
  • 625
  • 3
  • 9
  • 23

7 Answers7

5

You can use the dynamic keyword for that.

dynamic b = l1.Items.GetItemAt(0); 
var price = b.Price;
Wolfgang Ziegler
  • 1,675
  • 11
  • 23
4

Once an anonymous object goes out of scope, you can only access its properties using reflection (which is not recommended), dynamic (which makes you lose compile-time type safety) or some other hack.

The cleanest solution is to use a non-anonymous object, i.e. to define a class:

public class MyData {
    public int AA { get; set; }
    public string Description { get; set; }
    ...
}

...

l1.Items.Add(new MyData { AA = aa++, Description = descriptions[k], ...});

...

MyData b = (MyData) l1.Items.GetItemAt(0);
int aaValueOfB = b.AA;
Heinzi
  • 167,459
  • 57
  • 363
  • 519
  • `dynamic` still understands the underlying type of things. – Adam Houldsworth Jul 25 '12 at 13:12
  • @AdamHouldsworth: It [bypasses static type checking](http://msdn.microsoft.com/en-us/library/dd264736.aspx). – Heinzi Jul 25 '12 at 13:36
  • I never said otherwise, but `dynamic`, at runtime, has a very good understanding of the underlying object. The DLR stops things like invalid casts, enforces member accessibility, etc. Granted this is at runtime, but with good unit test coverage and some common sense, the `dynamic` keyword can be quite safe to use. I just wouldn't recommend it for this particular question. – Adam Houldsworth Jul 25 '12 at 13:42
  • @AdamHouldsworth: Ah, thanks, I see your point. I've modified my answer to clarify this ("you lose *compile-time* type safety"). – Heinzi Jul 25 '12 at 13:57
2

You could use the dynamic feature in c# 4, something like this:

dynamic item = l1.Items.GetItemAt(0);
double price = item.Price;

You could also use reflection (which dynamic uses anyway under the covers):

object item = l1.Items.GetItemAt(0);
Type t = item.GetType();
PropertyInfo pi = item.GetProperty("Price");
object price = pi.GetValue(item, null);

or, if it makes sense in the application, just declare it as a regular class, and use it as such.

SWeko
  • 30,434
  • 10
  • 71
  • 106
2

Once it has gone into object, you cannot cast it out. You have two options:

  • Use the dynamic keyword to duck-type the values out.

    dynamic d = l1.Items.GetItemAt(0);
    var price = d.Price;
    
  • Use an actual class instead of an anonymous type.

Personally, I'd make a class:

public class ItemsModel
{
    // Define the properties, etc.
}

As you'll likely want to have INotifyPropertyChanged implemented in order to data bind.

Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
2

As the guys already said, you can use the dynamic keyword from C#. Another option (in case you know your object structure) is using reflection to get the relevant property and extract its value.

List<object> collection = new List<object>
{
    new { Age1 = 1, Name = "Mr. Someone" } 
};            

// you can use reflection
object anonymous = collection.First();
var parameterInfo = anonymous.GetType().GetProperty("Name");
string name1 = (string)parameterInfo.GetValue(anonymous, null);

// another way
dynamic dynamicObject = collection.First();
string name2 dynamicObject.Name;
Tamir
  • 3,833
  • 3
  • 32
  • 41
0

Try this:

private static T GetAnonType<T>(T type, object obj)
        {
            return (T)obj;
        }

Object obj= l1.Items.GetItemAt(0);

var info = GetAnonType(new { AA = aa++, Description = descriptions[k], Shop = names[k + 2], Price = price},obj);

use default values for arguments like AA,Description etc.

then you can use , info.AA, info.Price etc.

Embedd_0913
  • 16,125
  • 37
  • 97
  • 135
0

I am new to Anonymous types but you will propably need to cast object to that type:

private static T CastTo<T>(this Object x, T targetType)
{
    return (T)x;
}
...
var tmp = new { AA = 0, Description = "", Shop = "", Price = 0.0}
tmp = l1.Items.GetItemAt(0).CastTo(tmp);
string price= "Price = " + tmp.Price;

Be sure that tmp properties will be initialized with correct types.

Pablo notPicasso
  • 3,031
  • 3
  • 17
  • 22