我有一个特定的需求,允许用户使用DataGrid插入新记录而不是使用新的子窗体。
如果有人能够推荐好的资源或为这个特定任务提供样例,那将是对我很大的帮助。
在CodeProject上有一篇关于WPF DataGrid + MVVM设计模式的文章:
编辑:粘贴了适合您问题的部分。 完整文章:http://www.codeproject.com/Articles/30905/WPF-DataGrid-Practical-Examples
本示例演示如何使用DataGrid通过绑定执行CRUD操作,其中数据库集成通过数据访问层(DAL)解耦。
架构
此示例是一个简单的CRUD应用程序,允许用户编辑Northwind数据库中Customers表中的项目。该示例具有数据访问层,该层公开查找/删除/更新方法,这些方法对简单数据对象进行操作,并且具有呈现层,该层以适当的方式调整这些对象,以便它们可以被WPF框架有效地绑定。因为我们只执行CRUD功能,所以我没有添加业务逻辑层(BLL);如果您是纯粹主义者,则可以添加一个经过的BLL;但是,我觉得它对这个示例的帮助很小。
此架构中的关键类如下所示:
数据访问层提供了一个接口来管理客户数据对象的生命周期。实现此接口的类使用类型化的 DataSet 作为数据库集成层,但是这对于 DAL 的客户端是隐藏的。有了这个层,我们不会直接耦合到数据库模式或生成的数据集模式,也就是说,我们可以更改我们的模式,但仍然向我们的客户提供以下接口:public interface ICustomerDataAccessLayer
{
/// Return all the persistent customers
List<CustomerDataObject> GetCustomers();
/// Updates or adds the given customer
void UpdateCustomer(CustomerDataObject customer);
/// Delete the given customer
void DeleteCustomer(CustomerDataObject customer);
}
public class CustomerDataObject
{
public string ID { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
}
public CustomerObjectDataProvider()
{
dataAccessLayer = new CustomerDataAccessLayer();
}
public CustomerUIObjects GetCustomers()
{
// populate our list of customers from the data access layer
CustomerUIObjects customers = new CustomerUIObjects();
List<CustomerDataObject> customerDataObjects = dataAccessLayer.GetCustomers();
foreach (CustomerDataObject customerDataObject in customerDataObjects)
{
// create a business object from each data object
customers.Add(new CustomerUIObject(customerDataObject));
}
customers.CollectionChanged += new
NotifyCollectionChangedEventHandler(CustomersCollectionChanged);
return customers;
}
void CustomersCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (object item in e.OldItems)
{
CustomerUIObject customerObject = item as CustomerUIObject;
// use the data access layer to delete the wrapped data object
dataAccessLayer.DeleteCustomer(customerObject.GetDataObject());
}
}
}
public delegate void ItemEndEditEventHandler(IEditableObject sender);
public event ItemEndEditEventHandler ItemEndEdit;
#region IEditableObject Members
public void BeginEdit() {}
public void CancelEdit() {}
public void EndEdit()
{
if (ItemEndEdit != null)
{
ItemEndEdit(this);
}
}
#endregion
当向CustomerUIObjects集合添加项目时,此事件将为集合中的所有项目处理,处理程序仅简单地转发事件:
public class CustomerUIObjects : ObservableCollection<CustomerDataObject>
{
protected override void InsertItem(int index, CustomerUIObject item)
{
base.InsertItem(index, item);
// handle any EndEdit events relating to this item
item.ItemEndEdit += new ItemEndEditEventHandler(ItemEndEditHandler);
}
void ItemEndEditHandler(IEditableObject sender)
{
// simply forward any EndEdit events
if (ItemEndEdit != null)
{
ItemEndEdit(sender);
}
}
public event ItemEndEditEventHandler ItemEndEdit;
}
public CustomerUIObjects GetCustomers()
{
// populate our list of customers from the data access layer
CustomerUIObjects customers = new CustomerUIObjects();
List<CustomerDataObject> customerDataObjects = dataAccessLayer.GetCustomers();
foreach (CustomerDataObject customerDataObject in customerDataObjects)
{
// create a business object from each data object
customers.Add(new CustomerUIObject(customerDataObject));
}
customers.ItemEndEdit += new ItemEndEditEventHandler(CustomersItemEndEdit);
customers.CollectionChanged += new
NotifyCollectionChangedEventHandler(CustomersCollectionChanged);
return customers;
}
void CustomersItemEndEdit(IEditableObject sender)
{
CustomerUIObject customerObject = sender as CustomerUIObject;
// use the data access layer to update the wrapped data object
dataAccessLayer.UpdateCustomer(customerObject.GetDataObject());
}
我不知道关于此主题有什么好的文章,但我不认为会有问题;只要绑定到包含具有默认构造函数的对象的 ObservableCollection 或 ListCollectionView(我认为没有其他限制),DataGrid 就会处理得非常好。您绑定到的集合必须有一种添加新项的方法,这就是为什么您需要绑定到 ICollection 或 IEditableCollectionView - 最好使用后者,因为它具有特定的选项来控制项目的创建 - 请参见AddNew
、CanAddNew
等,这些 DataGrid 能够很好地处理。