Насколько плох следующий фрагмент кода? - PullRequest
1 голос
/ 11 февраля 2009

Мой вопрос прост: насколько плох следующий фрагмент кода? Как бы ты сделал это?

CancelEventHandler _windowClosing;
private CancelEventHandler WindowClosing 
{
  set
  {
    clearEventHandlerList();
    this.Closing += value;
    _windowClosing = value;


    /*
     * if calling the method with null parameters,
     * it will set up itself as the primary control on the Window
     */
    _windowClosing(null,null);
  }
  get
  {
    return _windowClosing;
  }
}

private readonly CancelEventHandler[] CONTROLS = null;
private int current = 0;

public InitializerForm()
{
  InitializeComponent();

  /*
   * these are the handlers for the different controls,
   * in the order of appereance to the user
   */
  STATES = new CancelEventHandler[] { handler1, handler2, etc. };

  WindowClosing = CONTROLS[0];
}

private void clearEventHandlerList()
{
  foreach (CancelEventHandler c in CONTROLS)
  {
    this.Closing -= c;
  }
}

private void handler1(object obj, CancelEventArgs e)
{
  if (obj == null)
  {
    //hide every other control, but this one, also set up if necessary
  }
  else
  {
    //do something

    WindowClosing = CONTROLS[++current]; // set the next control to show

    e.Cancel = true;
  }
}

Дело в том, что код не будет закрывать форму, а вместо этого показывать на ней другой компонент, а также задавать способ обработки (это мобильная платформа, поэтому нажатие кнопки ОК в верхней части создает событие закрытия ). Это происходит потому, что отображение нескольких форм (4 или 5) одна за другой для пользователя заставляет приложение мигать, а также очень раздражает, в то время как замена только компонентов намного плавнее. Эта модель работает, но кажется очень неприятной, и я бы хотел более чистый способ справиться с этим.

Обновление: Я обновил пример кода, чтобы имена переменных были довольно понятными. Тем не менее, я убежден, что это ужасно, (а) но не уверен, насколько, и что более важно, (б) как сделать это лучше.

Обновление 2: Так что, похоже, код все еще немного загадочный.

Теперь вот в чем проблема: Я показываю пользователю форму, которая инструктирует его, что делать на нескольких языках. Он продолжает, нажимая OK в окне. Затем я спрашиваю его язык, а затем несколько вопросов (где его / ее GPS и т. Д.), Как это. После того, как он смог ответить на вопросы (это не должно занимать больше нескольких секунд каждый), я показываю ему заставку (я загружаю вещи в отдельном потоке), на которой есть картинка. Отображение этих форм одна за другой замедляет запуск всего приложения и заполняет лаги пользовательского интерфейса.

Вот что я делаю, чтобы обойти лаги: я помещаю содержимое окон в панели, помещаю эти панели одну на другую и скрываю каждую из них, кроме той, которая должна быть видна пользователю. (current переменная) Каждое из окон делает разные вещи, поэтому мне нужно дополнительно изменить обработчик события окна closing. В этом коде часть, которая включает панель, выполняет ту же функцию (handler1, handler2 и т. Д.), Что и часть, которая обрабатывает событие закрытия окна. Если аргументы null, он делает первое, если это не так (это означает, что он был вызван пользователем), он делает второе.

Мне нужно расширяемое решение для этого, чтобы я мог вставлять и удалять диалоги в любое время (порядок и указатели на функции хранятся в поле CONTROLS, и это, кажется, очень удобно, если вы на самом деле понять это. Хотя изменить содержание всего бланка никогда не бывает легко, для этого должен быть более простой и приятный способ, именно это я и ищу.

Надеюсь, на этот раз я смог объяснить, как работает модель.

Ответы [ 4 ]

2 голосов
/ 11 февраля 2009

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

1 голос
/ 11 февраля 2009

почему-то ваш код заставляет меня плакать, извините. я прочитал это дважды, и все, что я знаю об этом, - то, что это "делает Stuff" со словом "STATES"

если вам действительно нужна помощь, вам придется сначала поработать над ней самостоятельно ...

0 голосов
/ 14 февраля 2009

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

Но, предполагая, что вы все еще настроены на это, я бы начал с создания отдельного класса только для обработки стека / иерархии Panel. Назовите это PanelManager. Вы должны создать экземпляр PanelManager и связать его с основной формой, затем добавить к нему панели (возможно, привязанные к строке) и установить порядок. В основной форме вызовите обработчик закрытия PanelManager.CloseCurrentPanel (), и если больше нет панелей для отображения, то пришло время закрыть основную форму.

Время для псевдокода! Вот краткая идея для класса, я оставлю это вам для реализации:

public class PanelManager {
// constructor
public PanelManager (Form ownerForm);

// short-cut properties
public Panel this[int idx]
{ get; set; }

public int Index
{ get; set; }

// main functionality

public int AddPanel (Panel p);
public void SetPanelOrder (Panel p, int idx);
public void RemovePanel (Panel p);
public void RemovePanelAt (int idx);

// shows the first Panel
public void Show ();

// shows Panel[idx]
public void Show (int idx);

// adds the panel to the top of the stack and displays it
// returns the index of the panel
public int AddPanelAndShow (Panel p);

// hides the current panel, displays the one underneath it
// returns false if there are no more panels
public bool HideCurrentPanel ();
}

в конструкторе для главной формы, создайте его экземпляр с помощью нового PanelManager (this), затем в обработчике закрывающих событий вызовите panelManager.HideCurrentPanel () и выясните, нужно ли вам закрывать его после этого.

0 голосов
/ 12 февраля 2009

Используйте, XML! Это читабельно для человека!

Более серьезно-

Похоже, вы пытаетесь создать своего рода мастера настройки, поэтому я бы начал с изучения этого. Что касается вашего конкретного решения, я, как правило, выступаю против очень категорически против подхода «многослойной панели». Я делаю это потому, что поддерживаю приложения, написанные людьми, которые нашли этот подход, или подход «скрытые вкладки в элементе управления вкладками» хорошей идеей. Это не так, и сопровождающие будут проклинать ваше имя на долгие годы.

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

Другой возможностью может быть менее злая версия ваших слоистых панелей. Вместо добавления полдюжины панелей в одну форму создайте отдельный пользовательский элемент управления для каждой страницы мастера, а затем добавьте / удалите пользовательские элементы управления в содержащую форму. Это может избежать вашего мерцания и будет намного легче поддерживать, потому что каждая страница находится в отдельном контроле. Это также может упростить любую последующую функциональность кнопки «Назад» и сделать ваши структуры данных более естественными, поскольку эти пользовательские элементы управления будут связаны с определенным логическим битом данных. Это все еще не идеально, но, вероятно, достаточно хорошо для одноразового решения.

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

<Questions>
    <Question type="Text"> <!-- generate a textbox for the answer field -->
        Favorite Color:
    </Question>
    <Question type="Number" range="0-255"> <!-- Maybe this is a spinner -->
        The answer to life, the universe, and everything:
    </Question>
</Questions>

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

...