Hel*_*iac 0 linq wpf ienumerable ieditableobject observablecollection
背景:
我正在编写一个WPF应用程序,严格遵循MVVM模式.我有一个BaseRepository类作为连接到不同数据库的通用接口(EF不是一个选项),一切正常; 这只是一个技术问题.
我使用一个名为NotifyingCollection的包装ObservableCollection来订阅IEditableObject的ItemEndEdit事件(我的ViewModelBase实体包装器实现了INotifyPropertyChanged和IEditableObject成员).
当在我的WPF DataGrid中编辑项目时调用ReadAll方法时,提供的代码示例将抛出" 'EditItem'不允许此视图 "异常.但是,如果我用注释掉的部分替换方法中的线,它就可以完美地工作!
题:
换句话说,它看起来像中继Linq.Enumerable.Where扩展方法而不是返回集合的IEnumerable版本从自定义集合中删除功能; 如果它们都是IEnumerable,为什么会这样呢?
代码示例:
namespace MyCompany.Common.Abstracts
{
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data.Common;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using MyCompany.Common.Extensions;
using MyCompany.Common.Utilities;
public abstract class BaseRepository<TEntity> : IDisposable where TEntity : ViewModelBase
{
protected BaseRepository()
{
this.EntitySet = new NotifyingCollection<TEntity>();
this.EntitySet.ItemEndEdit += new ViewModelBase.ItemEndEditEventHandler(ItemEndEdit);
this.EntitySet.CollectionChanged += new NotifyCollectionChangedEventHandler(CollectionChanged);
}
protected abstract NotifyingCollection<TEntity> EntitySet { get; set; }
protected virtual void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Debug.WriteLine(String.Format("Modify '{0}'", e.PropertyName), "PropertyChanged");
}
protected virtual void ItemEndEdit(IEditableObject sender)
{
this.Update(sender as TEntity);
}
protected virtual void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
var collection = (e.Action == NotifyCollectionChangedAction.Remove) ?
e.OldItems : e.NewItems;
foreach (TEntity entity in collection)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
entity.PropertyChanged += this.PropertyChanged;
this.Create(entity);
break;
case NotifyCollectionChangedAction.Remove:
entity.PropertyChanged -= this.PropertyChanged;
this.Delete(entity);
break;
default:
Debug.WriteLine(String.Format("{0} '{1}'", e.Action.ToString(), entity.DisplayName), "CollectionChanged");
break;
}
}
}
public virtual bool Create(TEntity entity)
{
Debug.WriteLine(String.Format("Create '{0}'", entity.DisplayName), "CollectionChanged");
return true;
}
public virtual IEnumerable<TEntity> Read(Expression<Func<TEntity, bool>> filter)
{
return this.EntitySet.Where(filter.Compile());
}
public virtual IEnumerable<TEntity> ReadAll()
{
return this.Read(x => true);
//return this.EntitySet;
}
public virtual bool Update(TEntity entity)
{
Debug.WriteLine(String.Format("Update '{0}'", entity.DisplayName), "ItemEndEdit");
return true;
}
public virtual bool Delete(TEntity entity)
{
Debug.WriteLine(String.Format("Delete '{0}'", entity.DisplayName), "CollectionChanged");
return true;
}
public virtual IEnumerable<TColumn> GetColumn<TColumn>(string columnName)
{
var lookupTable = this.Read(x => x != null);
List<TColumn> column = new List<TColumn>();
foreach (TEntity record in lookupTable)
{
column.Add(record.GetPropValue<TColumn>(columnName));
}
var result = column.Distinct();
foreach (TColumn element in result)
{
yield return element;
}
}
public abstract int Commit();
public abstract DbTransaction BeginTransaction();
public abstract void Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
来自MichaelLPerry的博客:使用ObservableCollection时常见的错误
ObservableCollection是必不可少的.Linq是声明性的.没有额外帮助,两者不能一起使用.
命令式代码明确地对某些事物起作用.使用ObservableCollection时,显式调用Add,Remove和其他方法来更改集合.您必须确切地决定何时以及如何采取这些行动.
声明性代码隐式生成一些东西.使用linq时,您可以声明集合的外观,过滤,映射和转换的方式.您没有明确修改集合.
这两种范式不混合.一旦在ObservableCollection上使用linq,它就不再可观察了.像Bindable Linq这样的开源项目填补了这一空白.但如果没有这些额外的帮助,当事情不起作用时,人们常常感到惊讶.
| 归档时间: |
|
| 查看次数: |
302 次 |
| 最近记录: |