Как обрабатывать подписку на события универсального типа? - PullRequest
2 голосов
/ 22 июня 2009

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

Я создал универсальный метод для отображения этих панелей:

private static T ShowPanel<T>(Control parent, params object[] parameters) where T: Panel
{
    T panelToShow = (T)Activator.CreateInstance(typeof(T), parameters);

    parent.Controls.Add(panelToShow);

    panelToShow.Dock = DockStyle.Fill;
    panelToShow.BringToFront();
    panelToShow.Show();

    return panelToShow;
}

Я использую это так, но я знаю, что должен быть лучший способ обработать подписку на событие.

private void ShellButton_Click(object sender, EventArgs e)
{
    if (CurrentSelectedSite == null)
    {
        AlertSelectSite();
        return;
    }

    SystemViewPanel panel = ShowPanel<SystemViewPanel>(this, CurrentSelectedSite.Systems);

    panel.SystemsListbox.DoubleClick += new EventHandler(ShellAccessSystemSelected);
}

Есть несколько кнопок, которые делают разные вещи. Если на сайте имеется несколько систем, отображается SystemViewPanel, чтобы выбрать систему для выполнения действия. Теперь я должен подписаться на другой именованный обработчик событий, чтобы указать, какое действие я хочу выполнить, поэтому код моей основной формы становится беспорядочным (т.е. ShellAccessSystemSelected, DownloadFileSystemSelected, ViewSystemSystemSelected и т. Д.).

Редактировать

Я думаю, что можно обобщить тот факт, что я покажу панель, которая позволяет пользователю выбирать систему для большинства инструментов в моем приложении. Однако для каждого отдельного инструмента требуется другое действие в зависимости от инструмента, который инициировал создание SystemViewPanel.

Ответы [ 2 ]

0 голосов
/ 22 июня 2009

Эта SystemViewPanel довольно незначительна. Все, что он делает, это предоставляет способ выбора имени системы, поэтому я не хотел иметь 10 различных методов подписки на события, просто чтобы выбрать имя системы. Вот что я придумал:

private void ShellButton_Click(object sender, EventArgs e)
{
    if (CurrentSelectedSite == null)
    {
        AlertSelectSite();
        return;
    }

    SystemViewPanel systemSelectPanel = ShowPanel<SystemViewPanel>(this, CurrentSelectedSite.Systems);

    /*
    I decided that this since this panel is used quickly, I'd rather 
    keep the flow of what's happening in the same place. The line
    above shows the panel, a double click later, and I'm back to doing
    what the ShellButton does. 

    I've exposed a SystemSelected event, which just wraps the panel's 
    SystemsListBox.DoubleClick event.*/


    systemSelectPanel.SystemSelected += delegate(object s, EventArgs eArgs)
    {
        ListBox p = (ListBox)s;
        System system = (System)p.SelectedItem;

        if (system != null)
        {
            Process shell = new Process();
            shell.StartInfo = new ProcessStartInfo("cmd.exe",
            String.Format(@"/K psexec.exe \\{0} -u {1} -p {2} cmd.exe", system.IpAddress, CurrentSelectedSite.RemoteAccess.UserName, CurrentSelectedSite.RemoteAccess.DecryptedPassword));
            shell.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
            shell.StartInfo.UseShellExecute = true;


            shell.Start();
        }

        this.Controls.Remove(p.Parent);
        p.Parent.Dispose();
        this.SearchPanel.BringToFront();
    };
}
0 голосов
/ 22 июня 2009

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

SystemViewPanel panel = ShowPanel<SystemViewPanel>(
  this, 
  panel => {
    //Do the stuff you would do on click event, panel impl ensures this 
    // gets called at the right moment
  },
  CurrentSelectedSite.Systems);

Обновление из-за комментария:

Вам нужно знать, какие параметры требует ваша лямбда. Если вас устраивает сигнатура стандартного обработчика событий, вы можете просто использовать «EventHandler» в качестве типа параметра. Тогда ваша лямбда будет выглядеть как

(sender, args) => //Do stuff

Кроме того, если для вызываемой функции требуется только панель, вы должны использовать один из Action делегатов, который позволяет вам выражать методы с параметрами, но без возвращаемые значения.

Если вы хотите вернуть из вызываемой lmbda некоторое значение, которое затем будет обработано вызывающей стороной (вашей панелью), вы должны использовать любой из Func делегаты

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...