pyschedelisaurus Ответов: 1

Попытка внести изменения в две разные дочерние формы из основной формы с помощью пользовательских событий


У меня есть три формы:

Основная форма - Содержит коллекцию списков, созданную внутри, и две кнопки, где создаются экземпляры QuestionForm и ListViewForm.
public static List<Items> listOfItems = new List<Items>();

public List<Items> ItemList
{
   get { return listOfItems; }
   set { listOfItems = value; }
}

private void displayListViewToolStripMenuItem_Click(object sender, EventArgs e)
{
    ListViewForm lvf = new ListViewForm();
    lvf.Show();
}

private void newQuestioFormButton_Click(object sender, EventArgs e)
{
    QuestionForm qf = new QuestionForm();
    qf.Show();
    
    //Adds new item created to listOfItems 
    qf.ObjectCreatedToList += ObjectCreatedToListCollectionHandler;
}

QuestionForm - Содержит элементы управления для ввода пользователем значений, эти значения хранятся внутри переменной-члена класса, которая создается как объект и затем добавляется в коллекцию списков в основной форме

public EventHandler ObjectCreatedToList;

//Class Property that assigns values to member variables
public Items Info
{
    get
      {
        //Instantiates new Team class, assigns member variables to control values and returns new Team object
      }
    set
      {
        //set control values to Team member variables
      }  
}

private void addItemToolStripButton_Click(object sender, EventArgs e)
{
    if(ObjectCreatedToList != null)
    {
        ObjectCreatedToList(this, new EventArgs());
    }
    //Some Validation here to prevent control values to reset

    //If all control values are entered, this will clear the controls
    Info = new Items();
}

ListViewForm - Содержит ListView, где при добавлении элементов в коллекцию списков в форме QuestionForm они также должны быть добавлены в элемент управления listview

Проблема, с которой я сталкиваюсь, заключается в том, что при открытии всех трех форм элемент управления listview внутри формы ListViewForm должен обновляться по мере создания новых объектов формой QuestionForm.

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

Что я уже пробовал:

Я пробовал что-то похожее на это:

QuestionForm
public EventHandler ItemAlsoAddedToListViewChange;

private void addItemToolStripButton_Click(object sender, EventArgs e)
{
    if(ObjectCreatedToList != null)
    {
        ObjectCreatedToList(this, new EventArgs());
    }
    if(ItemAlsoAddedToListViewChange != null)
    {
        ItemAlsoAddedToListViewChange(this, new EventArgs());
    }
    //Some Validation here to prevent control values to reset

    //If all control values are entered, this will clear the controls
    Info = new Items();
}

ListViewForm
public void UpdateListViewHandler(object sender, EventArgs e)
{
    MainForm mf = sender as MainForm;
    forech(Items itm in mf.ItemList)
    {
         ListViewItem lvi = new ListViewItem();
         lvi.Text = itm.IconName;
         lvi.ImageIndex = itm.ItemIconIndex;
         lvi.Tag = itm;

         itemListViewControl.Items.Add(displayIcon);      
}

Основная форма
private void displayListViewToolStripMenuItem_Click(object sender, EventArgs e)
{
    ListViewForm lvf = new ListViewForm();
    QuestionForm qf = sender as QuestionForm();
    gf.ItemAlsoAddedToListViewChange += UpdateListViewHandler;
    lvf.Show();
}


Но это дало мне исключение ArgumentNullException.

Кто-нибудь может помочь? И уточните, что я делаю не так? Спасибо.

1 Ответов

Рейтинг:
1

OriginalGriff

ОК. Основная проблема здесь заключается в том, что вы не сохраняете ссылку ни на одну из форм при их создании - поэтому вы можете" найти " форму только тогда, когда получите событие и сможете получить к нему доступ через sender параметр обработчика событий.
Кроме того, есть забава в том, что, поскольку вы используете Show для отображения каждой формы, вы можете легко открыть сразу несколько версий одной и той же формы - так какую же из них вы должны обновить? И из какой версии другой формы?

Вы обращаетесь с этим неправильно: ваши ListViewForm и QuestionForm не должны иметь ни малейшего представления о том, что MainForm (или друг с другом) действительно существуют, они должны отчитываться перед родительской Mainform через события, которые затем используют свойства и методы на дочерних элементах для их обновления.

Итак, предположим, что вы хотите ограничить детей одним экземпляром, показывающим каждый из них:
1) Создайте частную ссылочную переменную ListViewForm и QuestionForm уровня класса и установите для них значение null.
2)Когда вы должны показать экземпляр формы, проверьте переменную. Если он не равен нулю, то форма уже видна, и вам ничего не нужно делать (но вы можете установить на нее фокус). Если это не так, создайте новый экземпляр, установите переменную и добавьте обработчик для события FormClosing.
2) Когда происходит событие закрытия, установите переменную в null.

Теперь добавьте в форму вопроса событие, которое обрабатывается в основной форме и указывает на наличие новых данных - добавьте свойство (или метод) для извлечения новых данных.
В обработчике форму mainform, принести новые данные, и передать его ListViewForm для того, чтобы обновить себя.

Это, вероятно, звучит сложно, но это не так, на самом деле - это очень очевидно, как только вы поймете это.
Взгляните на это: Передача информации между двумя формами, Часть 3: Ребенок ребенку[^]- он включает в себя пример.


pyschedelisaurus

Предполагается, что listviewform создается только один раз, но QuestionForm может быть создан несколько раз (потому что в MainForm также есть текстовое поле только для чтения, которое ведет подсчет количества открытых форм вопросов).

Что касается ListViewForm, то я использовал приведенный ниже код внутри того места, где он когда-то был создан, чтобы предотвратить открытие пользователем более одного экземпляра:

if (displayListViewToolStripMenuItem.Проверено = = верно)
{
// Проверка формы для предотвращения второго экземпляра
если ((ТЗМ == значение null) || (ПДК != нуль &амп;&амп; тлв.IsDisposed))
{
тлв.Показать();
}
если (!тлв.Видно)
{
тлв.Показать();
}
ещё
{
тлв.BringToFront();
}
}
ещё
{
//Если опция отображения будет нажата снова, это предотвратит ее снятие
displayListViewToolStripMenuItem.Проверено = истина;
}

OriginalGriff

Затем вы выбираете соответствующий экземпляр из параметра отправителя обработчика событий и извлекаете из него данные.
И вам либо не нужна переменная QuestionForm уровня класса, либо вы делаете ее коллекцией, в которую добавляете и удаляете экземпляры, если вам нужно получить к ним доступ без события по другой причине.