Добавление нескольких событий расширения программно не будет работать

У меня возникла проблема с добавлением события Expanded в мои расширители. У меня есть расширители в моем окне, и я хочу получить эффект, когда я расширяю свой расширитель, все остальные упадут. Я пишу функции, которые позволяют мне это делать, и это работает правильно. Проблема в том, что у меня есть 96 расширителей. Я не хочу добавлять 96 событий для расширения и 96 событий для свертывания, поэтому я подумал, что могу добавить это программно.

посмотрите на код:

    private void InitExpanders()
    {
        var expanders = GetExpanders(); // List<Expander> - list of expanders
        for (int i = 0; i < expanders.Count; i++)
        {
            if (i % 6 == 1)
            {
                    expanders[i - 1].Expanded += new RoutedEventHandler(delegate(object sender, RoutedEventArgs args)
                    {
                        DisableBigExpanders(1); // problem is here!
                    });
            }
        }
    }

этот код работает нормально, но для каждого параметра функции расширителя будет 1. Я пытался добавить целое число и увеличить его, но это не сработает.

    private void InitExpanders()
    {
        var expanders = GetExpanders();
        int x = 0;
        for (int i = 0; i < expanders.Count; i++)
        {
            if (i % 6 == 1)
            {
                    expanders[i - 1].Expanded += new RoutedEventHandler(delegate(object sender, RoutedEventArgs args)
                    {
                        DisableBigExpanders(x);
                    });
                    x++;
            }
        }
    }

Спасибо за все ответы.


person Brzooz    schedule 24.02.2012    source источник
comment
Есть лучший способ сделать это: blogs.microsoft.co.il/blogs/tomershamam/archive/2008/08/04/   -  person Joulukuusi    schedule 25.02.2012


Ответы (1)


Я подозреваю, что вы обнаружите, что x в делегате всегда является самым высоким значением, достигнутым во время цикла. Это связано с тем, как компилятор создает экземпляр определенного вами анонимного метода. Он смотрит, какие захваченные внешние переменные существуют вокруг делегата, и решает, требуются ли ему отдельные экземпляры или можно использовать один экземпляр. В этом случае у вас нет захваченных внешних переменных; следовательно, компилятору разрешено использовать один и тот же экземпляр делегата и, следовательно, одно и то же значение x.

Чтобы обойти эту проблему, все, что вам нужно сделать, это добавить более детализированную переменную непосредственно перед делегатом и присвоить ей значение x. Это будет работать:

private void InitExpanders()
{
    var expanders = GetExpanders();
    int x = 0;
    for (int i = 0; i < expanders.Count; i++)
    {
        if (i % 6 == 1)
        {
                int y = x++;
                expanders[i - 1].Expanded += delegate
                {
                    DisableBigExpanders(y);
                };
        }
    }
}

Подробнее об этой теории см. здесь: http://en.csharp-online.net/ECMA-334%3A_14.5.15.4_Anonymous_method_evaluation

person Neo    schedule 03.04.2012