【问题标题】:make or declare ObservableCollection<a> variable global where a=anonymous type使或声明 ObservableCollection<a> 变量为全局变量,其中 a=匿名类型
【发布时间】:2012-04-04 01:55:56
【问题描述】:

我想将列表视图数据上下文设置为等于可观察集合,以便对集合的更改可以反映在我的列表视图上。我将 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
                });

【问题讨论】:

  • 你绝对需要这个匿名类型吗?查询是否会返回与您指定的字段不同的字段?
  • 你说得对,我只是想节省时间,因为我在其他地方需要此功能,但我可能最终浪费了更多时间..
  • 您有一些选择,使用命名类型是最快的。我会发布一个更详细的答案。

标签: c# observablecollection datacontext


【解决方案1】:

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

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
(基本上你不能返回匿名类型 - 缺少这样的技巧 - 类型的“推断”是这背后的原因)。

【讨论】:

  • 没有意识到你可以为泛型类型添加扩展方法,这太棒了。
  • 你可以用静态方法做任何你能做的事情(你可以让方法和类一样通用)——只需为第一个参数添加“this”——虽然有点简化。
【解决方案2】:

在不能使用类型推断的地方使用匿名类型是不可能的,因此你不能,例如,声明一个匿名类型的类字段或属性。但是,有一个不明显的方法是使用类型推断,让您跨方法共享匿名对象。

正如我在评论中提到的,您最简单的选择是只使用命名类型;这将允许您将 ObservableCollection&lt;&gt; 定义为类级变量,或者在您的类中的其他位置对您的 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# 如何实现匿名类型的晦涩细节。它本身不是“黑客”,因为行为是由规范保证的,但它的工作范围受到严重限制。如果你只有一两个这样的集合,我肯定会倾向于给你的类型命名。

【讨论】:

  • 方法:ObservableCollection&lt;T&gt; Cast&lt;T&gt;(object obj, T typedobj) 给我一个编译错误说:Cannot convert type 'T' to 'System.Collections.ObjectModel.ObservableCollection&lt;T&gt;
  • 是的,我的回答中有错字,抱歉。类型转换错误的参数。现已修复。
  • 虽然我更喜欢扩展方法版本 :)
  • 只是风格问题:)(我不会为此发布我的答案,但我们几乎同时发布) - 无论我们如何表达,这仍然​​是一个“黑客”它,更有趣的编码
  • 我不知道;事实上,C# 规范明确保证这将起作用,这使我更有可能使用它,而不是依赖 GetHashCode() 的实现
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-22
  • 2015-07-25
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多