536cd135cc
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
251 lines
8.1 KiB
C#
251 lines
8.1 KiB
C#
//---------------------------------------------------------------------
|
|
// <copyright file="ObjectViewEntityCollectionData.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//
|
|
// @owner Microsoft
|
|
// @backupOwner Microsoft
|
|
//---------------------------------------------------------------------
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data.Objects.DataClasses;
|
|
using System.Data.Objects.Internal;
|
|
using System.Diagnostics;
|
|
using System.Data.Common;
|
|
|
|
namespace System.Data.Objects
|
|
{
|
|
/// <summary>
|
|
/// Manages a binding list constructed from an EntityCollection.
|
|
/// </summary>
|
|
/// <typeparam name="TViewElement">
|
|
/// Type of the elements in the binding list.
|
|
/// </typeparam>
|
|
/// <typeparam name="TItemElement">
|
|
/// Type of element in the underlying EntityCollection.
|
|
/// </typeparam>
|
|
/// <remarks>
|
|
/// The binding list is initialized from the EntityCollection,
|
|
/// and is synchronized with changes made to the EntityCollection membership.
|
|
/// This class always allows additions and removals from the binding list.
|
|
/// </remarks>
|
|
internal sealed class ObjectViewEntityCollectionData<TViewElement, TItemElement> : IObjectViewData<TViewElement>
|
|
where TItemElement : class
|
|
where TViewElement : TItemElement
|
|
{
|
|
private List<TViewElement> _bindingList;
|
|
|
|
private EntityCollection<TItemElement> _entityCollection;
|
|
|
|
private readonly bool _canEditItems;
|
|
|
|
/// <summary>
|
|
/// <b>True</b> if item that was added to binding list but not underlying entity collection
|
|
/// is now being committed to the collection.
|
|
/// Otherwise <b>false</b>.
|
|
/// Used by CommitItemAt and OnCollectionChanged methods to coordinate addition
|
|
/// of new item to underlying entity collection.
|
|
/// </summary>
|
|
private bool _itemCommitPending;
|
|
|
|
/// <summary>
|
|
/// Construct a new instance of the ObjectViewEntityCollectionData class using the supplied entityCollection.
|
|
/// </summary>
|
|
/// <param name="entityCollection">
|
|
/// EntityCollection used to populate the binding list.
|
|
/// </param>
|
|
internal ObjectViewEntityCollectionData(EntityCollection<TItemElement> entityCollection)
|
|
{
|
|
_entityCollection = entityCollection;
|
|
|
|
_canEditItems = true;
|
|
|
|
// Allow deferred loading to occur when initially populating the collection
|
|
_bindingList = new List<TViewElement>(entityCollection.Count);
|
|
foreach (TViewElement entity in entityCollection)
|
|
{
|
|
_bindingList.Add(entity);
|
|
}
|
|
}
|
|
|
|
#region IObjectViewData<TViewElement> Members
|
|
|
|
public IList<TViewElement> List
|
|
{
|
|
get { return _bindingList; }
|
|
}
|
|
|
|
public bool AllowNew
|
|
{
|
|
get { return !_entityCollection.IsReadOnly; }
|
|
}
|
|
|
|
public bool AllowEdit
|
|
{
|
|
get { return _canEditItems; }
|
|
}
|
|
|
|
public bool AllowRemove
|
|
{
|
|
get { return !_entityCollection.IsReadOnly; }
|
|
}
|
|
|
|
public bool FiresEventOnAdd
|
|
{
|
|
get { return true; }
|
|
}
|
|
|
|
public bool FiresEventOnRemove
|
|
{
|
|
get { return true; }
|
|
}
|
|
|
|
public bool FiresEventOnClear
|
|
{
|
|
get { return true; }
|
|
}
|
|
|
|
public void EnsureCanAddNew()
|
|
{
|
|
// nop
|
|
}
|
|
|
|
public int Add(TViewElement item, bool isAddNew)
|
|
{
|
|
if (isAddNew)
|
|
{
|
|
// Item is added to bindingList, but pending addition to entity collection.
|
|
_bindingList.Add(item);
|
|
}
|
|
else
|
|
{
|
|
_entityCollection.Add(item);
|
|
// OnCollectionChanged will be fired, where the binding list will be updated.
|
|
}
|
|
|
|
return _bindingList.Count - 1;
|
|
}
|
|
|
|
public void CommitItemAt(int index)
|
|
{
|
|
TViewElement item = _bindingList[index];
|
|
|
|
try
|
|
{
|
|
_itemCommitPending = true;
|
|
|
|
_entityCollection.Add(item);
|
|
// OnCollectionChanged will be fired, where the binding list will be updated.
|
|
}
|
|
finally
|
|
{
|
|
_itemCommitPending = false;
|
|
}
|
|
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
if (0 < _bindingList.Count)
|
|
{
|
|
List<object> _deletionList = new List<object>();
|
|
|
|
foreach (object item in _bindingList)
|
|
{
|
|
_deletionList.Add(item);
|
|
}
|
|
|
|
_entityCollection.BulkDeleteAll(_deletionList);
|
|
// EntityCollection will fire change event which this instance will use to clean up the binding list.
|
|
}
|
|
}
|
|
|
|
public bool Remove(TViewElement item, bool isCancelNew)
|
|
{
|
|
bool removed;
|
|
|
|
if (isCancelNew)
|
|
{
|
|
// Item was previously added to binding list, but not entity collection.
|
|
removed = _bindingList.Remove(item);
|
|
}
|
|
else
|
|
{
|
|
removed = _entityCollection.RemoveInternal(item);
|
|
// OnCollectionChanged will be fired, where the binding list will be updated.
|
|
}
|
|
|
|
return removed;
|
|
}
|
|
|
|
public ListChangedEventArgs OnCollectionChanged(object sender, CollectionChangeEventArgs e, ObjectViewListener listener)
|
|
{
|
|
ListChangedEventArgs changeArgs = null;
|
|
|
|
switch (e.Action)
|
|
{
|
|
case CollectionChangeAction.Remove:
|
|
// An Entity is being removed from entity collection, remove it from list.
|
|
if (e.Element is TViewElement)
|
|
{
|
|
TViewElement removedItem = (TViewElement)e.Element;
|
|
|
|
int oldIndex = _bindingList.IndexOf(removedItem);
|
|
if (oldIndex != -1)
|
|
{
|
|
_bindingList.Remove(removedItem);
|
|
|
|
// Unhook from events of removed entity.
|
|
listener.UnregisterEntityEvents(removedItem);
|
|
|
|
changeArgs = new ListChangedEventArgs(ListChangedType.ItemDeleted, oldIndex /* newIndex*/, -1 /* oldIndex*/);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CollectionChangeAction.Add:
|
|
// Add the entity to our list.
|
|
if (e.Element is TViewElement)
|
|
{
|
|
// Do not process Add events that fire as a result of committing an item to the entity collection.
|
|
if (!_itemCommitPending)
|
|
{
|
|
TViewElement addedItem = (TViewElement)e.Element;
|
|
|
|
_bindingList.Add(addedItem);
|
|
|
|
// Register to its events.
|
|
listener.RegisterEntityEvents(addedItem);
|
|
|
|
changeArgs = new ListChangedEventArgs(ListChangedType.ItemAdded, _bindingList.Count - 1 /* newIndex*/, -1 /* oldIndex*/);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CollectionChangeAction.Refresh:
|
|
foreach (TViewElement entity in _bindingList)
|
|
{
|
|
listener.UnregisterEntityEvents(entity);
|
|
}
|
|
|
|
_bindingList.Clear();
|
|
|
|
foreach(TViewElement entity in _entityCollection.GetInternalEnumerable())
|
|
{
|
|
_bindingList.Add(entity);
|
|
|
|
listener.RegisterEntityEvents(entity);
|
|
}
|
|
|
|
changeArgs = new ListChangedEventArgs(ListChangedType.Reset, -1 /*newIndex*/, -1/*oldIndex*/);
|
|
break;
|
|
}
|
|
|
|
return changeArgs;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|