创建可编辑的DataGrid时出错

时间:2012-11-08 18:10:31

标签: c# wpf linq entity-framework datagrid

我已经成功地使用LINQ。我正在尝试使用从LINQ查询收集的子集在WPF应用程序中创建可编辑的数据网格:

var LookUpEvents = from d in ThisData.Events.Local
                   where d.StartDate.Value.Date <= DateTime.Now.Date &&
                   (d.EndDate.HasValue == false || d.EndDate.Value.Date >= DateTime.Now.Date)
                   select d;
RangeEventGrid.ItemsSource = LookUpEvents;
RangeEventGrid.Items.Refresh();

此查询有效,并且填充了数据网格,但是当尝试抛出此异常时,我无法编辑数据网格:

"'EditItem' is not allowed for this view."
   at System.Windows.Controls.ItemCollection.System.ComponentModel.IEditableCollectionView.EditItem(Object item)
   at System.Windows.Controls.DataGrid.EditRowItem(Object rowItem)

使用以下方法加载完整数据集时

ThisData.Events.Load();
FullEventGrid.ItemsSource = ThisData.Events.Local;

一切正常,数据可编辑。使用的XAML是相同的(我也尝试交换绑定的数据网格,完整的结果仍然可编辑,查询仍抛出异常),这些之间的唯一区别是查询。当我尝试更改查询时,我最终会遇到一个新的异常:

The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

用于此的查询:

var LookUpEvents = from d in ThisData.Events
                   where d.StartDate.Value.Date <= DateTime.Now.Date &&
                   (d.EndDate.HasValue == false || d.EndDate.Value.Date >= DateTime.Now.Date)
                   select d;
LookUpEvents.Load(); //Exception thrown here.
RangeEventGrid.ItemsSource = LookUpEvents;
RangeEventGrid.Items.Refresh();

关于该异常的奇怪之处(至少对我来说很奇怪)是我在其他没有抛出异常的查询中使用DateTime比较,例如在另一个地方的这个查询工作正常:

var LookUpSessions = from d in ThisData.Sessions
                     where d.EndTime.Hour >= (DateTime.Now.Hour - 1) && d.StartTime.Hour <= (DateTime.Now.Hour + 2)
                     && d.Event.IsActive == true
                     orderby d.StartTime.Hour, d.StartTime.Minute
                     select d;

是否无法将LINQ查询结果绑定到DataGrid以进行编辑?如果是这样的话,那似乎是一个巨大的疏忽。我觉得我很可能只是缺少一些基本的东西,因为LINQ,WPF和EF对我来说都是全新的。

提前致谢。

2 个答案:

答案 0 :(得分:4)

使GridView中的编辑数据可以you cannot use an IEnumerable<T> or IQueryable<T>作为项目来源。您需要一个实现IListIEnumerable<T>IQueryable<T>的集合类型。

一种可能的解决方案是从LINQ查询中创建ObservableCollection<T>(确实实现IList):

RangeEventGrid.ItemsSource = new ObservableCollection<Event>(LookUpEvents);

这也是

的原因
FullEventGrid.ItemsSource = ThisData.Events.Local;

确实有效,因为Local已经是ObservableCollection<Event>类型。

您的第一个查询不会抛出异常(尽管您使用的是DateTime.Date),因为它不是LINQ到实体/数据库查询。它是一个LINQ-to-Objects查询,在Local集合的内存中运行。没有涉及数据库查询。

如果删除Local,则运行LINQ-to-Entities,而LINQ-to-Entities不支持LINQ-to-Objects所做的所有方法和属性,尤其是它不支持{{1} (但显然支持DateTime.Date)。

要在LINQ-to-Entities查询中按DateTime.Hour执行比较,您可以使用EntityFunctions

Date

或许var today = DateTime.Now.Date; var LookUpEvents = from d in ThisData.Events where EntityFunction.TruncateTime(d.StartDate) <= today && (!d.EndDate.HasValue || EntityFunction.TruncateTime(d.EndDate) >= today) select d; 函数也是一个选项。

答案 1 :(得分:1)

问题解决了!

为绑定添加了.ToList(),它确实有效!

完整的LINQ查询:

var LookUpEvents = from d in ThisData.Events.Local
                   where d.StartDate.Value.Date <= DateTime.Now.Date &&
                   (d.EndDate.HasValue == false || d.EndDate.Value.Date >= DateTime.Now.Date)
                   select d;

// Old binding: RangeEventGrid.ItemsSource = LookUpEvents;
// New binding:
RangeEventGrid.ItemsSource = LookUpEvents.ToList(); // .ToList() Fixes it!
RangeEventGrid.Items.Refresh();

http://xkcd.com/979/

为荣