Нет. Вам нужен полноразмерный парсер для этого типа проблем.
Вы редко создаете новый экземпляр класса коллекции в классе. Создайте его один раз и очистите его, а не создайте новый список. (и использовать ObservableCollection, поскольку он уже унаследовал интерфейс INotifyCollectionChanged )
private readonly ObservableCollection<T> list;
public ctor() {
list = new ObservableCollection<T>();
list.CollectionChanged += listChanged;
}
public ObservableCollection<T> List { get { return list; } }
public void Clear() { list.Clear(); }
private void listChanged(object sender, NotifyCollectionChangedEventArgs args) {
// list changed
}
Таким образом, вам нужно только один раз подключить события и выполнить «сброс», вызвав метод clear вместо того, чтобы проверять значение null или равенство первому списку в наборе доступа для свойства.
У меня есть решение, когда кто-то вызывает метод Generic из объекта IList.add (object). Чтобы вы также получили уведомление.
using System;
using System.Collections;
using System.Collections.Generic;
namespace YourNamespace
{
public class ObjectDoesNotMatchTargetBaseTypeException : Exception
{
public ObjectDoesNotMatchTargetBaseTypeException(Type targetType, object actualObject)
: base(string.Format("Expected base type ({0}) does not match actual objects type ({1}).",
targetType, actualObject.GetType()))
{
}
}
/// <summary>
/// Allows you to react, when items were added or removed to a generic List.
/// </summary>
public abstract class NoisyList<TItemType> : List<TItemType>, IList
{
#region Public Methods
/******************************************/
int IList.Add(object item)
{
CheckTargetType(item);
Add((TItemType)item);
return Count - 1;
}
void IList.Remove(object item)
{
CheckTargetType(item);
Remove((TItemType)item);
}
public new void Add(TItemType item)
{
base.Add(item);
OnItemAdded(item);
}
public new bool Remove(TItemType item)
{
var result = base.Remove(item);
OnItemRemoved(item);
return result;
}
#endregion
# region Private Methods
/******************************************/
private static void CheckTargetType(object item)
{
var targetType = typeof(TItemType);
if (item.GetType().IsSubclassOf(targetType))
throw new ObjectDoesNotMatchTargetBaseTypeException(targetType, item);
}
#endregion
#region Abstract Methods
/******************************************/
protected abstract void OnItemAdded(TItemType addedItem);
protected abstract void OnItemRemoved(TItemType removedItem);
#endregion
}
}
Если вы не хотите или не можете преобразовать в Observable Collection, попробуйте следующее:
public class EventList<T> : IList<T> /* NOTE: Changed your List<T> to IList<T> */
{
private List<T> list; // initialize this in your constructor.
public event ListChangedEventDelegate ListChanged;
public delegate void ListChangedEventDelegate();
private void notify()
{
if (ListChanged != null
&& ListChanged.GetInvocationList().Any())
{
ListChanged();
}
}
public new void Add(T item)
{
list.Add(item);
notify();
}
public List<T> Items {
get { return list; }
set {
list = value;
notify();
}
}
...
}
Теперь, для вашего свойства, вы сможете сократить свой код до этого:
public EventList List
{
get { return m_List.Items; }
set
{
//m_List.ListChanged -= List_ListChanged;
m_List.Items = value;
//m_List.ListChanged += List_ListChanged;
//List_ListChanged();
}
}
Почему? Установка чего-либо в EventList.Items вызовет вашу приватную notify()
.
IList<T>
!
– jp2code
8 October 2012 в 17:03
new
приведет к тому, что ((IList)list).Add(item)
не вызовет метод уведомления.
– Patrick
8 October 2012 в 17:04
notify()
к этому добавлению свойства.
– jp2code
8 October 2012 в 17:16
new
- я просто использовал то, что у него было. Я предполагаю, что у него есть причины.
– jp2code
8 October 2012 в 17:19
Если ObservableCollection не является для вас решением, вы можете попробовать следующее:
A) Внедрить пользовательские EventArgs, которые будут содержать новый атрибут Count, когда событие будет запущено.
public class ChangeListCountEventArgs : EventArgs
{
public int NewCount
{
get;
set;
}
public ChangeListCountEventArgs(int newCount)
{
NewCount = newCount;
}
}
B) Внедрите собственный список, который наследует от List и переопределяет атрибут Count и конструкторы в соответствии с вашими потребностями:
public class CustomList<T> : List<T>
{
public event EventHandler<ChangeListCountEventArgs> ListCountChanged;
public new int Count
{
get
{
ListCountChanged?.Invoke(this, new ChangeListCountEventArgs(base.Count));
return base.Count;
}
}
public CustomList()
{ }
public CustomList(List<T> list) : base(list)
{ }
public CustomList(CustomList<T> list) : base(list)
{ }
}
C) Наконец, подпишитесь на свое событие:
var myList = new CustomList<YourObject>();
myList.ListCountChanged += (obj, e) =>
{
// get the count thanks to e.NewCount
};
ObservableCollection - это список с событием CollectionChanged
ObservableCollection.CollectionChanged Event
Как подключить обработчик событий, см. ответ от Patrick. +1
Не уверен, что вы ищете, но я использую это для коллекции с одним событием, которое срабатывает при добавлении, удалении и изменении.
public class ObservableCollection<T>: INotifyPropertyChanged
{
private BindingList<T> ts = new BindingList<T>();
public event PropertyChangedEventHandler PropertyChanged;
// This method is called by the Set accessor of each property.
// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void NotifyPropertyChanged( String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public BindingList<T> Ts
{
get { return ts; }
set
{
if (value != ts)
{
Ts = value;
if (Ts != null)
{
ts.ListChanged += delegate(object sender, ListChangedEventArgs args)
{
OnListChanged(this);
};
}
NotifyPropertyChanged("Ts");
}
}
}
private static void OnListChanged(ObservableCollection<T> vm)
{
// this will fire on add, remove, and change
// if want to prevent an insert this in not the right spot for that
// the OPs use of word prevent is not clear
// -1 don't be a hater
vm.NotifyPropertyChanged("Ts");
}
public ObservableCollection()
{
ts.ListChanged += delegate(object sender, ListChangedEventArgs args)
{
OnListChanged(this);
};
}
}
public ObservableCollection<T> List { get; private set; }
Я пойду с этим. – Martin 9 October 2012 в 10:10