如何在 C# 中将项目添加到集合之前触发事件?

发布于 2024-08-09 10:56:34 字数 739 浏览 8 评论 0原文

我想在将项目添加到 BindingList 之前进行一些处理。我看到有一个 ListChanged 事件,但在添加项目后会触发该事件。 AddNew 事件仅在调用 AddNew 方法(而不是 Add 方法)时触发。以前有人做过这样的事情吗?

更新:

我创建了以下类,当在 IList 上调用 Add 方法时,我的新 Add 方法被触发。那么,我是否遇到了我在其他地方读过的选角问题?如果我从集合中删除 ISpecialCollection 接口,则不会调用我的 Add 方法。有人可以解释为什么它的行为不同吗?如果我使用 ISpecialCollection< 是否会遇到转换问题?界面?

public interface ISpecialCollection<T> : IList<T>
{
}

public class SpecialCollection<T> : BindingList<T>, ISpecialCollection<T>
{
  public new void Add (T item)  
  {
    base.Add(item);    
  }
}

class Program
{
  static void Main(string[] args)
  {
    IList<ItemType> list = new SpecialCollection<ItemType>();
    list.Add(new ItemType());
  }
}

I would like to do some processing before an item is added to a BindingList. I see there is an ListChanged event but this is fired after the item is added. The AddingNew event is only fired when the AddNew method (not the Add method) is called. Has anyone done something like this before?

UPDATE:

I have created the following classes and when the Add method is called on the IList, my new Add method gets triggered. So, do I have the casting problem that I've read in other places? If I removed the ISpecialCollection interface from the collection, my Add method doesn't get called. Can someone explain why it's acting differently? Do I have the casting problem if I use the ISpecialCollection< interface?

public interface ISpecialCollection<T> : IList<T>
{
}

public class SpecialCollection<T> : BindingList<T>, ISpecialCollection<T>
{
  public new void Add (T item)  
  {
    base.Add(item);    
  }
}

class Program
{
  static void Main(string[] args)
  {
    IList<ItemType> list = new SpecialCollection<ItemType>();
    list.Add(new ItemType());
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

や三分注定 2024-08-16 10:56:34

您应该重写受保护的 BindingList.InsertItem 方法 (MSDN )。 AddInsert 等都调用此函数来执行实际的添加操作并引发适当的事件。引发您的事件,然后调用 base.InsertItem 来完成其余的工作。

You should override the protected BindingList.InsertItem method (MSDN). Add, Insert and such all call this to do the actual adding adding and raise appropriate events. Raise your event, and then call base.InsertItem to do the rest.

哥,最终变帅啦 2024-08-16 10:56:34

最直接的途径是对 Collection 类进行子类化。这是 BCL 中的集合类,它被设计为子类化并覆盖其行为。子类化其他类型(例如 BindingListList)只会给您带来痛苦。

一旦您对 Collection 进行子类化,您就可以重写 Add 并创建您自己的事件来侦听。

The most straightforward route is to subclass the Collection<T> class. This is the collection class in the BCL which is designed to be subclassed and have it's behavior overriden. Subclassing other types like BindingList<T> or List<T> will just cause you pain.

Once you subclass Collection<T>, you can override Add and create your own event to listen to.

丶情人眼里出诗心の 2024-08-16 10:56:34

我做了类似的事情,因为我需要捕获 ItemAdding 和 ItemAdded 事件

魔法位是新关键字,它将覆盖继承类的方法

// class that inherits generic List and hides the add item
public class ListWithEvents<T> : List<T>
    {
        public event EventHandler ItemAdding;
        public event EventHandler ItemAdded;

        public new void Add(T item)
        {
            if (ItemAdding != null)
                ItemAdding(item, EventArgs.Empty);

            base.Add(item);

            if (ItemAdded != null)
                ItemAdded(item, EventArgs.Empty);

        }
    }

// Using the class
protected override void OnLoad(EventArgs e)
    {

        ListWithEvents<int> lstI = new ListWithEvents<int>();
        lstI.ItemAdded += new EventHandler(lstI_ItemAdded);
        lstI.ItemAdding += new EventHandler(lstI_ItemAdding);
    }

    void lstI_ItemAdding(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }

    void lstI_ItemAdded(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }

I have done something similar as I needed to capture the ItemAdding and ItemAdded event

The magic bit is the new keyword that will override the inherited class' method

// class that inherits generic List and hides the add item
public class ListWithEvents<T> : List<T>
    {
        public event EventHandler ItemAdding;
        public event EventHandler ItemAdded;

        public new void Add(T item)
        {
            if (ItemAdding != null)
                ItemAdding(item, EventArgs.Empty);

            base.Add(item);

            if (ItemAdded != null)
                ItemAdded(item, EventArgs.Empty);

        }
    }

// Using the class
protected override void OnLoad(EventArgs e)
    {

        ListWithEvents<int> lstI = new ListWithEvents<int>();
        lstI.ItemAdded += new EventHandler(lstI_ItemAdded);
        lstI.ItemAdding += new EventHandler(lstI_ItemAdding);
    }

    void lstI_ItemAdding(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }

    void lstI_ItemAdded(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }
挽清梦 2024-08-16 10:56:34

像这样的东西:

  public class PreProcessBindingList<T> : Collection<T>
    {   
        public AddingNewEventHandler AddingNew;

        public override void Add(T item)
        {
            PreProcess(item);
            base.Add(item);

            AddingNewEventHandler addingNew = this.AddingNew;
            if (addingNew != null)
            {
                addingNew(this, new AddingNewEventArgs(item));
            }
        }
    }

Something like:

  public class PreProcessBindingList<T> : Collection<T>
    {   
        public AddingNewEventHandler AddingNew;

        public override void Add(T item)
        {
            PreProcess(item);
            base.Add(item);

            AddingNewEventHandler addingNew = this.AddingNew;
            if (addingNew != null)
            {
                addingNew(this, new AddingNewEventArgs(item));
            }
        }
    }
愿与i 2024-08-16 10:56:34

The right way to do this is to extend Collection<T> and override the InsertItem method. You can raise your event there before calling base.InsertItem.

浅唱ヾ落雨殇 2024-08-16 10:56:34

使用 C5 集合库。 C5 的集合已设置为能够在多个操作上触发事件,包括清除集合、添加项目、删除项目、插入项目和常规集合更改。

此外,C5 库集合在适当的情况下实现了 System.Collection.GenericICollectionIList 接口,因此可以作为即使库仅需要实现,例如 SCG.ICollection

编辑:我忘了提及您的部分要求;我上面提到的许多事件都是可取消的事件,并且在操作影响底层集合之前触发,允许您进行更改或拒绝添加、删除等。

Use the C5 collections library. C5's collections are already set up to be able to fire events on several operations, including clearing the collection, adding items, removing items, inserting items, and general collection changes.

As well, the C5 library collections implement the System.Collection.Generic ICollection and IList interfaces where appropriate, and so can be dropped in as the implementation even if a library is only expecting, e.g. an SCG.ICollection.

EDIT: I forgot to mention a portion of your requirements; many of those events I mentioned above are cancelable events, and are fired before the action has affected the underlying collection, allowing you to make changes or reject additions, removals, etc.

可是我不能没有你 2024-08-16 10:56:34

使用可观察集合。它具有监视集合何时更改的事件。我相信它主要用于 WPF,但我也将它用于 ASP.NET 项目。

Use ObservableCollection. It has events that monitor when the collection is changing. I believe that it is primarily used for WPF, but I have used it with ASP.NET projects also.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文