Добавление нескольких событий экспандеров программно не будет работать - PullRequest
2 голосов
/ 24 февраля 2012

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

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

    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++;
            }
        }
    }

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

1 Ответ

2 голосов
/ 03 апреля 2012

Я подозреваю, что вы находите 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

...