制作或声明ObservableCollection <a> variable global where a=anonymous type</a>

时间:2012-04-02 23:09:11

标签: c# observablecollection datacontext

我想将listview datacontext设置为等于可观察集合,以便对集合的更改可能反映在我的列表视图上。我创建了observable集合:

public static ObservableCollection<T> ToObservableCollection<T>(IEnumerable<T> enumeration)
{
     return new ObservableCollection<T>(enumeration);
}

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{

           Entities.DatabaseModel m = new Entities.DatabaseModel();
           var q = from t in m.TimeSheet                            
                    join emp in m.Employees on t.idEmployee equals emp.id
                    where emp.id == CurrentEmploye.id
                    select new
                    {
                        firstName = emp.firstName,
                        lastName = emp.lastName,
                        position = emp.position,
                        clockInDate = t.clockInDate,
                        clockOutDate = t.clockOutDate,
                    };
           // here I create the observablecollection!!!!!!!!!!!!!!
           listView1.DataContext = ToObservableCollection(q); 
}

现在我的问题是,如果我想向ObservableCollection添加项目,我该怎么办?如果我做listView1.DataContext.Add(这将导致错误。

换句话说,我有方法

    private void btnClockIn_Click(object sender, RoutedEventArgs e)
    {
         // I will like to add items to the observable collection in here

这是我尝试过的,但不起作用:

    dynamic collection; 


private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
       // CurrentEmploye some employee
       Entities.DatabaseModel m = new Entities.DatabaseModel();
       var q = from t in m.TimeSheet                            
                join emp in m.Employees on t.idEmployee equals emp.id
                where emp.id == CurrentEmploye.id
                select new
                {
                    firstName = emp.firstName,
                    lastName = emp.lastName,
                    position = emp.position,
                    clockInDate = t.clockInDate,
                    clockOutDate = t.clockOutDate,
                };

       collection = ToObservableCollection(q); 
 }


    private void btnClockIn_Click(object sender, RoutedEventArgs e)
    {

         collection.Add(new
                {
                    firstName = "Antonio",
                    lastName = "Nam",
                    position = "Amin",
                    clockInDate = DateTime.Now,
                    clockOutDate = DateTime.Now
                });

2 个答案:

答案 0 :(得分:3)

你可以通过使用类似的'模板'匿名变量来“欺骗”它。
例如代码方法就像......

static ObservableCollection<T> CastToEnumerable<T>(this T template, object value)
{
    return (ObservableCollection<T>)value;
}

......并使用类似的东西......

var list = new
{
    firstName = "",
    lastName = "",
    position = "",
    clockInDate = DateTime.MinValue,
    clockOutDate = DateTime.MinValue
}.CastToEnumerable(context);
foreach (var value in list)
{ 
}

...为了您的目的,仍然建议使用正常的命名类 你可以在这里找到更多关于类似问题的信息...
Cast to Anonymous Type
(基本上你不能返回匿名类型 - 缺少这样的技巧 - '推断'的类型就是这背后的原因)。

答案 1 :(得分:1)

在无法使用类型推断的地方使用匿名类型是不可能的,因此您不能,例如,声明匿名类型的类字段或属性。但是,有一些非显而易见的方法是使用类型推断,它允许您跨方法共享匿名对象。

正如我在评论中提到的,最简单的选择是使用命名类型;这样您就可以将ObservableCollection<>定义为类级变量,或者在类中的其他地方对DataContext进行类型转换。

根据您需要使用此代码的频率,还有第二个选项涉及将object类型转换为您的匿名类型。这要求您在要使用匿名类型的每个位置知道 按哪种顺序 。它还要求匿名类型的每次使用都存在于同一程序集中的 - 这可以保证编译器将匿名类型统一到单个基础类型中。

如果符合您的要求,您可以使用这样的“技巧”:

ObservableCollection<T> Cast<T>(object obj, T typedobj)
{
  return (ObservableCollection<T>)obj;
}

private void btnClockIn_Click(object sender, RoutedEventArgs e)
{
  var temp = new 
  { 
    firstName = string.Empty, 
    lastName = string.Empty, 
    position = string.Empty, 
    clockInDate = DateTime.Min, 
    clockOutDate = DateTime.Now 
  };

  var collection = Cast(lstView1.DataContext, temp);
  collection.Add(...);
}

让我再说一遍,这是一个有点混乱的“技巧”,它充分利用了C#如何实现匿名类型的模糊细节。这不是一个“黑客”本身,因为规范保证了这种行为,但是这种行为的严重限制。如果你只有一两个这样的收藏品,我肯定会倾向于给你的类型名称。