我想将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
});
答案 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#如何实现匿名类型的模糊细节。这不是一个“黑客”本身,因为规范保证了这种行为,但是这种行为的严重限制。如果你只有一两个这样的收藏品,我肯定会倾向于给你的类型名称。