StandardCollectionView.cs :  » 2.6.4-mono-.net-core » System.Windows » System » Windows » Data » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Windows 
System.Windows » System » Windows » Data » StandardCollectionView.cs
using System;
using System.ComponentModel;
using System.Collections.Specialized;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace System.Windows.Data{

  sealed class StandardCollectionView : ICollectionView, IEditableCollectionView, INotifyPropertyChanged, IDeferRefresh {

    public event NotifyCollectionChangedEventHandler CollectionChanged;
    public event EventHandler CurrentChanged;
    public event CurrentChangingEventHandler CurrentChanging;
    public event PropertyChangedEventHandler PropertyChanged;

    INPCProperty<bool> canAddNew;
    INPCProperty<bool> canCancelEdit;
    INPCProperty<bool> canRemove;
    INPCProperty<object> currentAddItem;
    INPCProperty<object> currentEditItem;
    INPCProperty<bool> isAddingNew;
    INPCProperty<bool> isCurrentAfterLast;
    INPCProperty<bool> isCurrentBeforeFirst;
    INPCProperty<bool> isEditingItem;
    INPCProperty<bool> isempty;
    INPCProperty<NewItemPlaceholderPosition> newItemPlaceholderPosition;

    INPCProperty<CultureInfo> culture;
    Predicate<object> filter;
    List<object> filteredList;

    public IList ActiveList {
      get {
        if (Filter == null && GroupDescriptions.Count == 0 && SortDescriptions.Count == 0)
          return SourceCollection;
        return filteredList;
      }
    }

    public bool CanAddNew {
      get { return canAddNew.Value; }
      private set { canAddNew.Value = value;}
    }

    public bool CanCancelEdit {
      get { return canCancelEdit.Value; }
      private set {
        if (CanCancelEdit != value)
          canCancelEdit.Value = value;
      }
    }

    public bool CanRemove {
      get { return canRemove.Value; }
      private set { canRemove.Value = value;}
    }

    PropertyComparer Comparer {
      get { return new PropertyComparer (SortDescriptions); }
    }

    public bool IsAddingNew {
      get { return isAddingNew.Value; }
      private set { isAddingNew.Value = value;}
    }

    public bool IsEditingItem {
      get { return isEditingItem.Value; }
      private set { isEditingItem.Value = value;}
    }

    public NewItemPlaceholderPosition NewItemPlaceholderPosition {
      get { return newItemPlaceholderPosition.Value; }
      set { newItemPlaceholderPosition.Value = value;}
    }

    public bool CanFilter {
      get { return true; }
    }

    public bool CanGroup {
      get { return true; }
    }

    public bool CanSort {
      get { return true; }
    }

    public CultureInfo Culture {
      get { return culture.Value; }
      set { culture.Value = value; }
    }

    public object CurrentAddItem {
      get { return currentAddItem.Value; }
      private set { currentAddItem.Value = value; }
    }

    public object CurrentEditItem {
      get { return currentEditItem.Value; }
      private set { currentEditItem.Value = value; }
    }

    public object CurrentItem {
      get; private set;
    }

    public int CurrentPosition {
      get; private set;
    }

    int IDeferRefresh.DeferLevel {
      get; set;
    }

    public Predicate<object> Filter {
      get { return filter; }
      set {
        filter = value;
        Refresh ();
      }
    }

    bool Grouping {
      get { return Groups != null; }
    }

    public ObservableCollection<GroupDescription> GroupDescriptions {
      get; private set;
    }

    public ReadOnlyObservableCollection<object> Groups {
      get; private set;
    }

    public bool IsCurrentAfterLast {
      get { return isCurrentAfterLast.Value; }
      private set {
        if (IsCurrentAfterLast != value)
          isCurrentAfterLast.Value = value;
      }
    }

    public bool IsCurrentBeforeFirst {
      get { return isCurrentBeforeFirst.Value; }
      private set {
        if (IsCurrentBeforeFirst != value)
          isCurrentBeforeFirst.Value = value;
      }
    }

    public bool IsEmpty {
      get; private set;
    }

    bool IsValidSelection {
      get { return CurrentPosition >= 0 && CurrentPosition < ActiveList.Count; }
    }

    ConstructorInfo ItemConstructor {
      get; set;
    }

    StandardCollectionViewGroup RootGroup {
      get; set;
    }

    public SortDescriptionCollection SortDescriptions {
      get; private set;
    }

    IEnumerable ICollectionView.SourceCollection {
      get { return SourceCollection; }
    }

    public IList SourceCollection {
      get; private set;
    }

    public StandardCollectionView (IList collection)
    {
      SourceCollection = collection;
      Func<PropertyChangedEventHandler> changed = () => PropertyChanged;

      canAddNew = INPCProperty.Create (() => CanAddNew, changed);
      canCancelEdit = INPCProperty.Create (() => CanCancelEdit, changed);
      canRemove = INPCProperty.Create (() => CanRemove, changed);
      culture = INPCProperty.Create (() => Culture, changed);
      currentAddItem = INPCProperty.Create (() => CurrentAddItem, changed);
      currentEditItem = INPCProperty.Create (() => CurrentEditItem, changed);
      isAddingNew = INPCProperty.Create (() => IsAddingNew, changed);
      isCurrentAfterLast = INPCProperty.Create (() => IsCurrentAfterLast, changed);
      isCurrentBeforeFirst = INPCProperty.Create (() => IsCurrentBeforeFirst, changed);
      isEditingItem = INPCProperty.Create (() => IsEditingItem, changed);
      isempty = INPCProperty.Create (() => IsEmpty, changed);
      newItemPlaceholderPosition = INPCProperty.Create (() => NewItemPlaceholderPosition, changed);

      SourceCollection = collection;
      SortDescriptions = new SortDescriptionCollection ();
      GroupDescriptions = new ObservableCollection<GroupDescription> ();

      var interfaces = SourceCollection.GetType ().GetInterfaces ();
      foreach (var t in interfaces) {
        if (t.IsGenericType && t.GetGenericTypeDefinition () == typeof (IList<>)) {
          Type type = t.GetGenericArguments () [0];
          ItemConstructor = type.GetConstructor (Type.EmptyTypes);
        }
      }

      UpdateCanAddNewAndRemove ();
      filteredList = new List <object> ();
      CurrentPosition = -1;
      IsEmpty = ActiveList.Count == 0;
      MoveCurrentToPosition (0);

      if (SourceCollection is INotifyCollectionChanged)
        ((INotifyCollectionChanged) SourceCollection).CollectionChanged += HandleSourceCollectionChanged;

      GroupDescriptions.CollectionChanged += (o, e) => Refresh ();
      ((INotifyCollectionChanged) SortDescriptions).CollectionChanged += (o, e) => {
        if (IsAddingNew || IsEditingItem)
          throw new InvalidOperationException ("Cannot modify SortDescriptions while adding or editing an item");
        Refresh ();
      };
    }

    void HandleSourceCollectionChanged (object sender, NotifyCollectionChangedEventArgs e)
    {
      // Firstly if we are copying the source collection into our filtered list, update
      // the copy with the new changes and compute the actual index of our item in the
      // sorted/grouped/filtered list.
      int actualOldIndex = -1;
      int actualNewIndex = -1;
      bool originalList = ActiveList == SourceCollection;
      NotifyCollectionChangedEventArgs modifed = e;
      if (!originalList) {
        switch (e.Action) {
        case NotifyCollectionChangedAction.Add:
          foreach (object o in e.NewItems)
            AddToFilteredAndGroupSorted (o);
          actualNewIndex = IndexOf (e.NewItems [0]);
          RaiseCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add, e.NewItems [0], actualNewIndex));
          break;

        case NotifyCollectionChangedAction.Remove:
          actualOldIndex = IndexOf (e.OldItems [0]);
          foreach (object o in e.OldItems)
            RemoveFromFilteredAndGroup (o);
          RaiseCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Remove, e.OldItems [0], actualOldIndex));
          break;

        case NotifyCollectionChangedAction.Replace:
          actualOldIndex = IndexOf (e.OldItems [0]);
          foreach (object o in e.OldItems)
            RemoveFromFilteredAndGroup (o);
          foreach (object o in e.NewItems)
            AddToFilteredAndGroupSorted (o);
          actualNewIndex = IndexOf (e.NewItems [0]);
          RaiseCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Remove, e.OldItems[0], actualOldIndex));
          RaiseCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add, e.NewItems [0], actualNewIndex));
          break;
  
        case NotifyCollectionChangedAction.Reset:
          filteredList.Clear ();
          RootGroup.ClearSubtree ();
          foreach (var o in SourceCollection)
            AddToFilteredAndGroup (o);
          modifed = e;
          break;
        }
      } else {
        // Raise the collection changed event
        RaiseCollectionChanged (modifed);
      }

      IsEmpty = ActiveList.Count == 0;

      // Finally update the selected item if needed.
      switch (e.Action) {
      case NotifyCollectionChangedAction.Add:
        if (originalList)
          actualNewIndex = e.NewStartingIndex;
        if (actualNewIndex <= CurrentPosition)
          MoveCurrentTo (CurrentPosition + 1);
        break;

      case NotifyCollectionChangedAction.Remove:
        if (originalList)
          actualOldIndex = e.OldStartingIndex;
        if (actualOldIndex < CurrentPosition) {
          MoveCurrentTo (CurrentPosition - 1);
        } else if (actualOldIndex == CurrentPosition) {
          if (CurrentAddItem == CurrentItem)
            MoveCurrentTo (CurrentPosition - 1);
          else
            MoveCurrentTo (CurrentPosition, true);
        }
        break;

      case NotifyCollectionChangedAction.Replace:
        MoveCurrentTo (CurrentPosition, true);
        break;

      case NotifyCollectionChangedAction.Reset:
        MoveCurrentTo (IndexOf (CurrentItem));
        break;
      }

    }

    void AddToFilteredAndGroup (object item)
    {
      // If we're adding an item because of a call to the 'AddNew' method, we
      //
      if (AddToFiltered (item, false) && Grouping && CurrentAddItem == null)
        RootGroup.AddInSubtree (item, Culture, GroupDescriptions);
    }

    void AddToFilteredAndGroupSorted (object item)
    {
      // If we're adding an item because of a call to the 'AddNew' method, we
      //
      if (AddToFiltered (item, true) && Grouping && CurrentAddItem == null)
        RootGroup.AddInSubtree (item, Culture, GroupDescriptions);
    }

    void RemoveFromFilteredAndGroup (object item)
    {
      if (RemoveFromFiltered (item) && Grouping)
        RootGroup.RemoveInSubtree (item);
    }

    bool AddToFiltered (object item, bool sorted)
    {
      // If we are not adding a new item and we have a filter, see if the item passes the filter
      if (CurrentAddItem == null && Filter != null)
        if (!Filter (item))
          return false;

      // Only do a sorted insert if we are not adding a new item
      if (CurrentAddItem == null && sorted && SortDescriptions.Count > 0) {
        int index = filteredList.BinarySearch (item, new PropertyComparer (SortDescriptions));
        if (index < 0)
          index = ~index;
        filteredList.Insert (index, item);
      } else {
        filteredList.Add (item);
      }
      return true;
    }

    bool RemoveFromFiltered (object item)
    {
      return filteredList.Remove (item);
    }

    public bool Contains (object item)
    {
      return ActiveList.Contains (item);
    }

    public IDisposable DeferRefresh ()
    {
      if (IsAddingNew || IsEditingItem)
        throw new InvalidOperationException ("Cannot defer refresh while adding or editing");

      return new Deferrer (this);
    }

    public IEnumerator GetEnumerator ()
    {
      if (GroupDescriptions.Count > 0 && RootGroup != null)
        return new GroupEnumerator (RootGroup);
      return ActiveList.GetEnumerator ();
    }

    int IndexOf (object item)
    {
      if (Grouping)
        return RootGroup.IndexOfSubtree (item);
      else
        return ActiveList.IndexOf (item);
    }
    public bool MoveCurrentTo (object item)
    {
      return MoveCurrentTo (IndexOf (item));
    }

    bool MoveCurrentTo (int position)
    {
      return MoveCurrentTo (position, false);
    }

    object ItemAtIndex (int index)
    {
      if (Groups == null)
        return index < 0 || index >= ActiveList.Count ? null : ActiveList [index];
      foreach (var o in this) {
        if (index == 0)
          return o;
        index --;
      }

      return null;
    }

    bool MoveCurrentTo (int position, bool force)
    {
      object newItem = ItemAtIndex (position);
      bool raiseEvents = CurrentItem != newItem;

      var h = CurrentChanging;
      if (raiseEvents && h != null) {
        CurrentChangingEventArgs e = new CurrentChangingEventArgs (true);
        h (this, e);
        if (e.Cancel)
          return true;
      }

      IsCurrentAfterLast = position == ActiveList.Count || ActiveList.Count == 0;
      IsCurrentBeforeFirst = position == -1 || ActiveList.Count == 0;
      UpdateCurrentPositionAndItem (position, newItem);

      var h2 = CurrentChanged;
      if (raiseEvents && h2 != null)
        h2 (this, EventArgs.Empty);

      return IsValidSelection;
    }

    public bool MoveCurrentToFirst ()
    {
      return MoveCurrentTo (0);
    }

    public bool MoveCurrentToLast ()
    {
      return MoveCurrentTo (ActiveList.Count - 1);
    }

    public bool MoveCurrentToNext ()
    {
      return CurrentPosition != ActiveList.Count && MoveCurrentTo (CurrentPosition + 1);
    }

    public bool MoveCurrentToPosition (int position)
    {
      return MoveCurrentTo (position);
    }

    public bool MoveCurrentToPrevious ()
    {
      return CurrentPosition != -1 && MoveCurrentTo (CurrentPosition - 1);
    }

    void RaiseCollectionChanged (NotifyCollectionChangedEventArgs e)
    {
      var h = CollectionChanged;
      if (h != null)
        h (this, e);
    }

    void RaisePropertyChanged (string propertyName)
    {
      var h = PropertyChanged;
      if (h != null)
        h (this, new PropertyChangedEventArgs (propertyName));
    }

    public void Refresh ()
    {
      if (IsAddingNew || IsEditingItem)
        throw new InvalidOperationException ("Cannot refresh while adding or editing an item");

      if (((IDeferRefresh) this).DeferLevel != 0)
        return;

      if (RootGroup == null)
        RootGroup = new StandardCollectionViewGroup (null, null, 0, false, SortDescriptions);

      Groups = null;
      RootGroup.ClearItems ();

      if (ActiveList != SourceCollection) {
        filteredList.Clear ();
        foreach (var item in SourceCollection)
          AddToFiltered (item, false);

        if (SortDescriptions.Count > 0)
          filteredList.Sort (new PropertyComparer (SortDescriptions));

        if (GroupDescriptions.Count > 0 && filteredList.Count > 0) {
          foreach (var item in filteredList)
            RootGroup.AddInSubtree (item, Culture, GroupDescriptions, false);
          Groups = RootGroup.Items;
        }
      }

      IsEmpty = ActiveList.Count == 0;
      int index = IndexOf (CurrentItem);
      if (index < 0 && CurrentPosition != -1 && !IsEmpty)
        index = 0;

      MoveCurrentTo (index, true);

      var h = CollectionChanged;
      if (h != null)
        h (this, new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Reset));
    }

    public object AddNew ()
    {
      if (((IDeferRefresh) this).DeferLevel != 0)
        throw new InvalidOperationException ("Cannot add a new item while refresh is deferred");

      if (ItemConstructor == null)
        throw new InvalidOperationException ("The underlying collection does not support adding new items");

      if (SourceCollection.IsFixedSize)
        throw new InvalidOperationException ("The source collection is of fixed size");

      // If there's an existing AddNew or Edit, we commit it. Commit the edit first because
      // we're not allowed CommitNew if we're in the middle of an edit.
      if (IsEditingItem)
        CommitEdit ();
      if (IsAddingNew)
        CommitNew ();

      var newObject = ItemConstructor.Invoke (null);
      // FIXME: I need to check the ordering on the events when the source is INCC
      CurrentAddItem = newObject;
      IsAddingNew = true;
      AddToSourceCollection (newObject);
      if (Grouping)
        RootGroup.AddItem (newObject, false);
      MoveCurrentTo (newObject);
      if (newObject is IEditableObject)
        ((IEditableObject) newObject).BeginEdit ();

      UpdateCanAddNewAndRemove ();
      return newObject;
    }

    void AddToSourceCollection (object item)
    {
      SourceCollection.Add (item);
      if (!(SourceCollection is INotifyCollectionChanged)) {
        HandleSourceCollectionChanged (SourceCollection, new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add, item, SourceCollection.Count - 1));
      }
    }

    void RemoveFromSourceCollection (object item)
    {
      int index = SourceCollection.IndexOf (item);
      SourceCollection.RemoveAt (index);
      if (!(SourceCollection is INotifyCollectionChanged)) {
        HandleSourceCollectionChanged (SourceCollection, new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Remove, item, index));
      }
    }

    public void CancelEdit ()
    {
      if (IsAddingNew)
        throw new InvalidOperationException ("Cannot cancel edit while adding new");

      if (IsEditingItem) {
        if (CanCancelEdit) {
          ((IEditableObject) CurrentEditItem).CancelEdit ();
        }
        CurrentEditItem = null;
        IsEditingItem = false;
        CanCancelEdit = false;
        UpdateCanAddNewAndRemove ();
      }
    }

    public void CancelNew ()
    {
      if (IsEditingItem)
        throw new InvalidOperationException ("Cannot CancelNew while editing an item");

      if (IsAddingNew) {
        if (CurrentAddItem is IEditableObject)
          ((IEditableObject) CurrentAddItem).CancelEdit ();
        if (Grouping) {
          RootGroup.RemoveItem (CurrentAddItem);
        }
        RemoveFromSourceCollection (CurrentAddItem);
        CurrentAddItem = null;
        IsAddingNew = false;
        UpdateCanAddNewAndRemove ();
      }
    }

    public void CommitEdit ()
    {
      if (IsAddingNew)
        throw new InvalidOperationException ("Cannot cancel edit while adding new");

      if (IsEditingItem) {
        var editItem = CurrentEditItem;

        CurrentEditItem = null;
        IsEditingItem = false;

        if (CanCancelEdit) {
          ((IEditableObject) editItem).EndEdit ();
          CanCancelEdit = false;
        }

        UpdateCanAddNewAndRemove ();

        int originalIndex = IndexOf (editItem);
        int newIndex;

        // If we're filtering the item out just nuke it
        if (Filter != null && !Filter (editItem)) {
          RemoveFromFilteredAndGroup (editItem);
          RaiseCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Remove, editItem, originalIndex));
          if (CurrentItem == editItem)
            MoveCurrentTo (CurrentPosition, true);
          return;
        }

        // We could also have changed the property which sorts it
        if (SortDescriptions.Count > 0) {
          // We can't just remove the item and binary search for the correct place as that will change the
          // order of elements which compare as equal and breaks more tests than it fixes. We need to first
          // check to see if the editItem is >= than the previous one and <= the next one. If that is true
          // we need to do nothing. Otherwise we need to binary search either the upper or lower half and
          // find the new index where the editItem should be placed.
          if (originalIndex > 0 && Comparer.Compare (filteredList [originalIndex - 1], editItem) > 0) {
            newIndex = filteredList.BinarySearch (0, originalIndex, editItem, Comparer);
          } else if (originalIndex < (filteredList.Count - 1) && Comparer.Compare (filteredList [originalIndex + 1], editItem) < 0) {
            newIndex = filteredList.BinarySearch (originalIndex + 1, filteredList.Count - (originalIndex + 1), editItem, Comparer);
          } else {
            // We're already in the right place.
            newIndex = originalIndex;
          }
        } else {
          // No sorting == no index change
          newIndex = originalIndex;
        }


        if (newIndex != originalIndex) {
          if (newIndex < 0)
            newIndex = ~newIndex;

           // When we remove the element from the original index, our newIndex will be off by 1 as everything
          // gets shuffled down so decrement it here.
          if (newIndex > originalIndex)
            newIndex --;

          filteredList.RemoveAt (originalIndex);
          filteredList.Insert (newIndex, editItem);
        }

        // We may have edited the property which controls which group the item is in
        // so re-seat it
        if (Grouping) {
          RootGroup.RemoveInSubtree (editItem);
          RootGroup.AddInSubtree (editItem, Culture, GroupDescriptions);
          newIndex = IndexOf (editItem);
        }

        if (originalIndex != newIndex) {
          RaiseCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Remove, editItem, originalIndex));
          RaiseCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add, editItem, newIndex));
          MoveCurrentTo (IndexOf (CurrentItem), true);
        }
      }
    }

    public void CommitNew ()
    {
      if (IsEditingItem)
        throw new InvalidOperationException ("Cannot CommitNew while editing an item");
      if (IsAddingNew) {
                if (CurrentAddItem is IEditableObject)
          ((IEditableObject) CurrentAddItem).EndEdit ();
        if (Filter != null && !Filter (CurrentAddItem)) {
          RemoveFromSourceCollection (CurrentAddItem);
        } else {
          // When adding a new item, we initially put it in the root group. Once it's committed
          // we need to place it in the correct subtree group.
          if (Grouping) {
            RootGroup.RemoveItem (CurrentAddItem);
            RootGroup.AddInSubtree (CurrentAddItem, Culture, GroupDescriptions);
          }

          // The item was not filtered out of the tree. Do we need to resort it?
          if (SortDescriptions.Count > 0) {
            // The newly added item is at the end of the array. If we're sorting, we may have to move it.
            // Use a binary search to figure out where the item should be in the list and put it in there.
            int actualIndex = SourceCollection.IndexOf (CurrentAddItem);
            int sortedIndex = filteredList.BinarySearch (0, filteredList.Count - 1, CurrentAddItem, new PropertyComparer (SortDescriptions));
            if (sortedIndex < 0)
              sortedIndex = ~sortedIndex;

            if (actualIndex != sortedIndex) {
              filteredList.RemoveAt (actualIndex);
              filteredList.Insert (sortedIndex, CurrentAddItem);
              RaiseCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Remove, currentAddItem, actualIndex));
              RaiseCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add, currentAddItem, sortedIndex));
              if (CurrentAddItem == CurrentItem)
                UpdateCurrentPositionAndItem (sortedIndex, CurrentAddItem);
            }
          }
        }
        CurrentAddItem = null;
        IsAddingNew = false;
        UpdateCanAddNewAndRemove ();
      }
    }

    public void EditItem (object item)
    {
      // We can't edit an item which hasn't been comitted.
      if (IsAddingNew && item == CurrentAddItem)
        return;

      if (IsAddingNew)
        CommitNew ();
      if (IsEditingItem)
        CommitEdit ();

      CurrentEditItem = item;
      IsEditingItem = true;
      if (item is IEditableObject) {
        CanCancelEdit = true;
        ((IEditableObject) item).BeginEdit ();
      }
      UpdateCanAddNewAndRemove ();
    }

    public void Remove (object item)
    {
      if (!CanRemove)
        throw new InvalidOperationException ("Removing is not supported by this collection");
      if (IsAddingNew || IsEditingItem)
        throw new InvalidOperationException ("Cannot remove an item when adding or editing an item");
      RemoveFromSourceCollection (item);
    }

    public void RemoveAt (int index)
    {
      if (!CanRemove)
        throw new InvalidOperationException ("Removing is not supported by this collection");
      if (IsAddingNew || IsEditingItem)
        throw new InvalidOperationException ("Cannot remove an item when adding or editing an item");
      RemoveFromSourceCollection (ItemAtIndex (index));
    }

    void UpdateCanAddNewAndRemove ()
    {
      var value = ItemConstructor != null && !SourceCollection.IsFixedSize && !IsEditingItem;
      if (value != CanAddNew)
        CanAddNew = value;

      value = !SourceCollection.IsFixedSize && !IsEditingItem && !IsAddingNew;
      if (value != CanRemove)
        CanRemove = value;
    }

    void UpdateCurrentPositionAndItem (int position, object item)
    {
      bool emitPositionChanged = CurrentPosition != position;
      bool emitItemChanged = CurrentItem != item;

      CurrentPosition = position;
      CurrentItem = item;

      if (emitPositionChanged)
        RaisePropertyChanged ("CurrentPosition");
      if (emitItemChanged)
        RaisePropertyChanged ("CurrentItem");
    }
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.