C#委托没有被删除

时间:2011-08-10 01:03:13

标签: c# delegation

在程序中,我使用图片框创建了多个面板。图片框被委托为可点击。我想让用户可以选择从订单中删除其中一个面板/图片框。现在,如果它被删除并且订单被重新排列,那么被删除的图片框之后的所有图片框都会保留其委托订单。所以在删除它之后点击它们中的任何一个,跳到它旁边的那个(即点击#9,它将转到#10)。我需要删除重新排序的委托并重新委托它们。我试过了:

int z2 = z;
var myClickDelegate = (EventHandler)delegate { clicked(z2, null); };
PicBx[z].Click += myClickDelegate;

创建和

PicBx[z].Click -= myClickDelegate;

删除

以及

int z2 = z;
PicBx[z].Click -= delegate { clicked(z2, null); };

但他们都没有删除原始授权。

4 个答案:

答案 0 :(得分:1)

你的第一种方法应该有用,但后一种方法不适用 因为当您执行PicBx[z].Click -= delegate { clicked(z2, null); };方法时,您不会删除旧委托,而是创建新委托,然后将其删除。

在第一次尝试时,这应该有效:

private void SomeMethod()
{
    var myClickDelegate = (EventHandler)delegate { clicked(z2, null); };
    PicBx[z].Click += myClickDelegat;
    //Do extra work
    PicBx[z].Click -= mayClickDelegat;
}

编辑:对评论进行配对: 我注意到你只是在你的委托添加clicked(z2, null),所以我假设你只是在第一个位置创建委托只是为了传递int z2来表示图片框索引。
您可以使用pictureBox.Tag将该索引与图片框本身放在一起,然后在点击事件中从标记中获取int

int z2 = z;
picBx[z].Tag = z2;//here we embedded the number with the picture box.
PicBx[z].Click += clicked;
...
PicBx[z].Click -= clicked;

在点击的事件中如此:

private void clicked(object sender, EventArgs e)
{
    PictureBox pictureBox = sender as PictureBox;

    if (pictureBox != null)
    {
        int number = Convert.ToInt32(pictureBox.Tag);
        ...
    }
}

Edit2:作为评论的配对,您似乎对clicked方法有不同的签名:

private void clicked(int tes,..
{
    Pnl[tes].BackColor = Color.Red;
}

这里我们只将其改为:

private void clicked(object sender, EventArgs e)
{
    PictureBox pictureBox = sender as PictureBox;//when user clicks on picture box it will be the sender parameter.

    if (pictureBox != null)
    {
        //we add number to each of picture boxes at there tags. "picBx[z].Tag = z2"
        int tes = Convert.ToInt32(pictureBox.Tag);
        pnl[tes].BackColor = Color.Red;
    }
}

答案 1 :(得分:1)

您不是要删除同一个委托。你应该尝试将你的代表存储在某个地方:

this.MyDelegate = delegate { clicked(z2, null); };

PicBx[z].Click += this.MyDelegate;


...

...


PicBx[z].Click -= this.MyDelegate;

但与这样的代表一起玩会导致糟糕的设计选择。您应该定义一个bool,您可以在其中确定是否执行了您的委托。

public void OnClick(object sender, ...)
{
    if(myBool)
    {
        ...
    }
}

答案 2 :(得分:0)

从你的评论到Jalal回答,看起来你可能真的需要这样的东西

How to remove all event handlers from a control

答案 3 :(得分:0)

这里有两个问题。

正如其他人所指出的那样,第一个是你需要删除你添加到事件处理程序的同一个委托实例。

第二个是你使用数组来存储你的图片框,你的处理程序正在使用索引来查找你的图片框,所以当你从数组中删除一个图片框时,所有的图片框的事件处理程序都在数组会指向错误的图片框。

以下是该做什么:

步骤1:更改事件处理程序以获取图片框的实例,而不是数组的索引。

步骤2:创建一个类级别字典,通过图片框保存您的委托引用:

Dictionary<PictureBox, EventHandler> _pictureBoxHandlers =
    new Dictionary<PictureBox, EventHandler>();

第3步:编写您的订阅代码:

//After the picture box is added to `PicBx`
var pb = PicBx[z];
var myClickDelegate = (EventHandler)delegate { clicked(pb, null); };
_pictureBoxHandlers[pb] = myClickDelegate;
pb.Click += myClickDelegate;

第4步:写下你的取消订阅代码:

//Before the picture box is removed from `PicBx`
var pb = PicBx[z];
if (_pictureBoxHandlers.ContainsKey(pb))
{
    var myClickDelegate = _pictureBoxHandlers[pb];
    pb.Click -= myClickDelegate;
    _pictureBoxHandlers.Remove(pb);
}

看看情况如何。