C # Делегация не удаляется - PullRequest
2 голосов
/ 10 августа 2011

В программе у меня есть несколько панелей, созданных с картинками.Графические блоки делегированы для кликабельности.Я хотел бы, чтобы у пользователя была возможность удалить одну из панелей / графических блоков из заказа.Прямо сейчас, если он удален, и порядок переставляет все графические блоки после того, как тот, который был удален, сохраняет свой делегированный порядок.Поэтому, нажимая на любой из них после того, который был удален, переходите к следующему по нему (т.е. нажмите на № 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 ]

1 голос
/ 10 августа 2011

Вы не пытаетесь удалить одного и того же делегата.Вы должны попытаться хранить своих делегатов где-нибудь:

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

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


...

...


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

Но игра с такими делегатами может привести к неправильному выбору дизайна.Вы должны определить bool, в котором вы будете определять, выполняете ли вы свой делегат или нет.

public void OnClick(object sender, ...)
{
    if(myBool)
    {
        ...
    }
}
1 голос
/ 10 августа 2011

Ваш первый метод должен работать, но последний не должен работать.потому что когда вы используете метод 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 и в событии click получить 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;

И так в событии 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;
    }
}
0 голосов
/ 10 августа 2011

У вас есть две проблемы здесь.

Во-первых, как уже отмечали другие, вам необходимо удалить тот же экземпляр делегата, который вы добавили в обработчик событий.

Во-вторых, вы используете массив для хранения ваших графических блоков, а ваши обработчики используют индекс для поиска вашего графического блока, поэтому при удалении графического блока из массива все обработчики событий для графических блоков выше в массив будет указывать на неправильную графическую рамку.

Вот что нужно сделать:

Шаг 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);
}

Посмотрите, как это происходит.

0 голосов
/ 10 августа 2011

Из вашего комментария к ответу на Джалал, похоже, вам действительно может понадобиться что-то вроде этого

Как удалить все обработчики событий из элемента управления

...