C# _Click Event Casting Sender и использование FindControl

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

В этом конкретном случае мне также сразу же не хватает соответствующей UpdatePanel, чтобы я мог добавить к ней динамически отображаемый GridView. Chart и UpdatePanel собраны вместе, имея одинаковые идентификаторы. И диаграмма, и панель обновлений динамически создаются во время выполнения.

Мне интересно, есть ли лучший / предпочтительный способ реализовать такое поведение.

protected void Chart_Click(object sender, ImageMapEventArgs e)
{
    Chart chart = (Chart)sender;
    UpdatePanel up = (UpdatePanel)chart.Parent.FindControl(chart.ID + "UP");

    GridView gv = new GridView();
    Dictionary<string, string> displayFields =
        new Dictionary<string, string>();

    // add data to displayFields by using the ImageMapEventArgs.PostBackValue
    // to create data for dictionary ...

    gv.DataSource = displayFields;
    gv.DataBind();
    up.ContentTemplateContainer.Controls.Add(gv);
}

Ответов (4)

Решение

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

  • Добавьте в диаграмму свойство под названием «LinkedPanel» и назначьте ему свою панель обновления.

    Вы увидите аналогичный шаблон, используемый в значке уведомления, где вы свяжете его с контекстным меню )

    Я думаю, что это особенно приятно, потому что, когда все сделано правильно, вы можете просто назначить связанный элемент управления в конструкторе форм. (Конечно, это не поможет с вашими динамически генерируемыми элементами управления)

  • Объедините оба элемента управления в один UserControl (если элементы управления всегда отображаются рядом друг с другом, это может быть правильным решением)

  • Создайте объект, который знает об обоих элементах управления, и попросите его обрабатывать события, которые они вызывают.

Я согласен, что в зависимости от имени мне кажется неправильным; Я был бы слишком смущен / нервничал, чтобы использовать его в производственном коде: - / (Если вы единственный разработчик, то я думаю, это зависит от вас ...)

Использование этих других подходов снижает вероятность того, что «невинное изменение», сделанное другим разработчиком, начнет вызывать неожиданные исключения.

Вместо этого используйте как.

Ваш гипс бросит, если не удастся.

Chart chart = sender as Chart;
if (chart == null)
   return; // or do something else

// the rest of your handler.

Я думаю, что отправлять отправителя безопасно, Chart потому что вы знаете, что это всегда Chart . Обратите внимание, что имя метода четное Chart_Click .

Можно, однако, сохранить ссылку на UpdatePanel в Chart «s Tag собственности. Это избавляет от уродства и риска поиска имени у родителя. Может быть трудно поддерживать, если вы постоянно меняете родителей или перемещаете панели.

Однако, если вы знаете на 100%, что они UpdatePanel будут там и будут правильно названы, в вашем подходе нет ничего "неправильного", ИМХО. Возможно, вы захотите добавить комментарий «не меняйте это имя» рядом со UpdatePanel.Name = строкой, в которой вы его инициализируете, хотя в целях безопасности. (Кстати, если вы не единственный, у кого есть доступ к вашему коду, 100% мгновенно упадут до 99,9%.)

В том, что вы сделали, нет ничего плохого. Но вы можете предотвратить ошибку приведения типов, используя "as" при явном приведении типов следующим образом.

если вы хотите узнать, является ли элемент управления UpdatePanel, вы можете сделать это с помощью GetType() метода

пример: sender.GetType().name даст вам имя элемента управления

protected void Chart_Click(object sender, ImageMapEventArgs e)
{
    Chart chart = (Chart)sender;
    control c = Parent.FindControl(chart.ID + "UP");
    UpdatePanel up ;

    if (c != null)
    {
       up = c as UpdatePanel;**


       GridView gv = new GridView();
       Dictionary<string, string> displayFields =
           new Dictionary<string, string>();

       // add data to displayFields by using the ImageMapEventArgs.PostBackValue
       // to create data for dictionary ...

       gv.DataSource = displayFields;
       gv.DataBind();
       up.ContentTemplateContainer.Controls.Add(gv);
   }
}