Windows forms доступ к элементам другой формы

Как обратиться к элементам одной формы из другой? Есть две формы и нужно получить доступ к объектам одной формы из другой.

Иногда бывает нужно обратиться к элементам какой-то формы из другой в процессе выполнения программы. Например, есть форма Form1, из нее мы открываем другую Form2 и теперь, работая в форме Form2 нужно обратиться, получить доступ к элементам родительской формы Form1. Я нашел несколько способов как это сделать.

1-й способ. Передача ссылки в public переменную.

Перед открытием формы, передаем ссылку на нужный элемент в переменную public вызываемой формы.

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form2 frm = new Form2();
            frm.but1 = this.button1; // передаем ссылку на кнопку в форму Form2
            frm.ShowDialog();
        }
    }
}

В форме Form2 переменная, в которую передавали ссылку, будет теперь соответствовать кнопке button1 из формы Form1

namespace WindowsApplication1
{
    public partial class Form2 : Form
    {
        public Button but1; // эта переменная будет содержать ссылку на кнопку button1 из формы Form1

        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            but1.Text = "test"; // меняем текст на кнопке button1 формы Form1
        }
    }
}

2-й способ. Передача ссылки в дочернюю форму.

Суть примерна та же, то и в 1-м способе. При открытии формы Form2 передаем в нее ссылку на элемент, который планируем потом менять.

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form2 frm = new Form2(this.button1); // передаем ссылку на кнопку в форму Form2
            frm.ShowDialog();
        }
    }
}

Теперь в форме Form2 нужно создать переменную, которая будет содержать ссылку на эту кнопку и через нее будем обращаться к кнопке на Form1 (строки 5,7,9 и 15).

namespace WindowsApplication1
{
    public partial class Form2 : Form
    {
        private Button but1; // эта переменная будет содержать ссылку на кнопку button1 из формы Form1

        public Form2(Button but) // получаем ссылку на кнопку в переменную but
        {
            but1 = but; // теперь but1 будет ссылкой на кнопку button1
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            but1.Text = "test"; // меняем текст на кнопке button1 формы Form1
        }
    }
}

3-й способ. Доступ ко всей родительской форме.

Чтобы осуществить это, нужно внести изменения в нескольких файлах, но зато при этом получим доступ ко всем элементам родительской формы и не нужно передавать ссылку на каждый элемент, как в 1-м способе.

Шаг 1. В файле Program.cs создаем публичную переменную f1 (строка 5).

namespace WindowsApplication1
{
    static class Program
    {
        public static Form1 f1; // переменная, которая будет содержать ссылку на форму Form1
        
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

Шаг 2. Открываем Form1.Designer.cs и в нем у элементов, к которым нужно будет обратиться из другой формы, меняем private на public. Например, сделаем доступной для изменений кнопку button1 на форме Form1.

public System.Windows.Forms.Button button1; // заменили private на public

Шаг 3. При создании формы Form1 присваиваем переменной f1 ссылку на эту форму (строка 7)

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            Program.f1 = this; // теперь f1 будет ссылкой на форму Form1
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form2 frm = new Form2();
            frm.ShowDialog();
        }
    }
}

Шаг 4. Теперь из абсолютно любой формы или из любого класса можно обратиться к элементу button1 находящемуся на Form1 так: Program.f1.button1. Например, пусть кнопка в Form2 поменяет текст кнопки на Form1:

namespace WindowsApplication1
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Program.f1.button1.Text = "test"; // Меняем текст на кнопке формы Form1
        }
    }
}

Change modifier from public to internal. .Net deliberately uses private modifier instead of the public, due to preventing any illegal access to your methods/properties/controls out of your project. In fact, public modifier can accessible wherever, so They are really dangerous. Any body out of your project can access to your methods/properties. But In internal modifier no body (other of your current project) can access to your methods/properties.

Suppose you are creating a project, which has some secret fields. So If these fields being accessible out of your project, it can be dangerous, and against to your initial ideas. As one good recommendation, I can say always use internal modifier instead of public modifier.

But some strange!

I must tell also in VB.Net while our methods/properties are still private, it can be accessible from other forms/class by calling form as a variable with no any problem else.

I don’t know why in this programming language behavior is different from C#. As we know both are using same Platform and they claim they are almost same Back end Platform, but as you see, they still behave differently.

But I’ve solved this problem with two approaches. Either; by using Interface (Which is not a recommend, as you know, Interfaces usually need public modifier, and using a public modifier is not recommend (As I told you above)),

Or

Declare your whole Form in somewhere static class and static variable and there is still internal modifier. Then when you suppose to use that form for showing to users, so pass new Form() construction to that static class/variable. Now It can be Accessible every where as you wish. But you still need some thing more.
You declare your element internal modifier too in Designer File of Form. While your Form is open, it can be accessible everywhere. It can work for you very well.

Consider This Example.

Suppose you want to access to a Form’s TextBox.

So the first job is declaration of a static variable in a static class (The reason of static is ease of access without any using new keywork at future).

Second go to designer class of that Form which supposes to be accessed by other Forms. Change its TextBox modifier declaration from private to internal. Don’t worry; .Net never change it again to private modifier after your changing.

Third when you want to call that form to open, so pass the new Form Construction to that static variable—>>static class.

Fourth; from any other Forms (wherever in your project) you can access to that form/control while From is open.

Look at code below (We have three object.
1- a static class (in our example we name it A)

2 — Any Form else which wants to open the final Form (has TextBox, in our example FormB).

3 — The real Form which we need to be opened, and we suppose to access to its internal TextBox1 (in our example FormC).

Look at codes below:

internal static class A
{
    internal static FormC FrmC;
}

FormB ...
{
    '(...)
    A.FrmC = new FormC();
    '(...)
}

FormC (Designer File) . . . 
{
     internal System.Windows.Forms.TextBox TextBox1;
}

You can access to that static Variable (here FormC) and its internal control (here Textbox1) wherever and whenever as you wish, while FormC is open.


Any Comment/idea let me know. I glad to hear from you or any body else about this topic more. Honestly I have had some problems regard to this mentioned problem in past. The best way was the second solution that I hope it can work for you. Let me know any new idea/suggestion.

Change modifier from public to internal. .Net deliberately uses private modifier instead of the public, due to preventing any illegal access to your methods/properties/controls out of your project. In fact, public modifier can accessible wherever, so They are really dangerous. Any body out of your project can access to your methods/properties. But In internal modifier no body (other of your current project) can access to your methods/properties.

Suppose you are creating a project, which has some secret fields. So If these fields being accessible out of your project, it can be dangerous, and against to your initial ideas. As one good recommendation, I can say always use internal modifier instead of public modifier.

But some strange!

I must tell also in VB.Net while our methods/properties are still private, it can be accessible from other forms/class by calling form as a variable with no any problem else.

I don’t know why in this programming language behavior is different from C#. As we know both are using same Platform and they claim they are almost same Back end Platform, but as you see, they still behave differently.

But I’ve solved this problem with two approaches. Either; by using Interface (Which is not a recommend, as you know, Interfaces usually need public modifier, and using a public modifier is not recommend (As I told you above)),

Or

Declare your whole Form in somewhere static class and static variable and there is still internal modifier. Then when you suppose to use that form for showing to users, so pass new Form() construction to that static class/variable. Now It can be Accessible every where as you wish. But you still need some thing more.
You declare your element internal modifier too in Designer File of Form. While your Form is open, it can be accessible everywhere. It can work for you very well.

Consider This Example.

Suppose you want to access to a Form’s TextBox.

So the first job is declaration of a static variable in a static class (The reason of static is ease of access without any using new keywork at future).

Second go to designer class of that Form which supposes to be accessed by other Forms. Change its TextBox modifier declaration from private to internal. Don’t worry; .Net never change it again to private modifier after your changing.

Third when you want to call that form to open, so pass the new Form Construction to that static variable—>>static class.

Fourth; from any other Forms (wherever in your project) you can access to that form/control while From is open.

Look at code below (We have three object.
1- a static class (in our example we name it A)

2 — Any Form else which wants to open the final Form (has TextBox, in our example FormB).

3 — The real Form which we need to be opened, and we suppose to access to its internal TextBox1 (in our example FormC).

Look at codes below:

internal static class A
{
    internal static FormC FrmC;
}

FormB ...
{
    '(...)
    A.FrmC = new FormC();
    '(...)
}

FormC (Designer File) . . . 
{
     internal System.Windows.Forms.TextBox TextBox1;
}

You can access to that static Variable (here FormC) and its internal control (here Textbox1) wherever and whenever as you wish, while FormC is open.


Any Comment/idea let me know. I glad to hear from you or any body else about this topic more. Honestly I have had some problems regard to this mentioned problem in past. The best way was the second solution that I hope it can work for you. Let me know any new idea/suggestion.

Цитата
Сообщение от pixel_61
Посмотреть сообщение

to4kin, что-то я не могу вкурить в ваш код… элемент DataGridView не виден ни в первой, ни во второй форме… да и как-то очень много не понятного для меня в нём… можете не много рассказать или объяснить его?

Что значит не виден ни в первой, ни во второй? Как минимум DataGridView должен быть виден в той форме, в которой его создали.

C#
1
public object[] AddInfoDataGrid

это функция для работы с DataGridView из вне, в данном случае она позволяет добавлять элемент только в 1 ячейку.
Для наглядности можно описать ее так:

C#
1
2
3
4
5
6
7
public object[] AddInfoDataGrid
        {
            set
            {                
                    DataGridView1.Rows[1].Cells[8].Value = value[0];                   
            }
        }

т.е. мы в строку под номером 1 в ячейку номер 8 записываем что-то.

Далее записываем в DataGridView1 значение из TextBox1

C#
1
2
3
4
mainForm.AddInfoDataGrid = new object[]
                                               {
                                                   TextBox1.Text,
                                               };

Посмотрите внимательнее на названия форм и элементов в вашем проекте, скорее всего проблема в этом.

Цитата
Сообщение от pixel_61
Посмотреть сообщение

to4kin, почему не безопасно? и к каким последствиям это может привести?

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

P.S. Выложите код двух ваших форм, посмотрим в чем там проблема.

Добавлено через 25 минут
Вот полностью рабочий пример с использованием ListBox’a:

From1:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public partial class Form1 : Form
    {
        private readonly Form2 form2;
 
        public Form1()
        {
            InitializeComponent();
            form2 = new Form2(this);
            form2.Show();
        }
 
        public object[] AddListBox
        {
            set
            {
                listBox1.Items.Add(value[0]);
            }
        }
    }

Form2:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public partial class Form2 : Form
    {
        private readonly Form1 form;
        
        public Form2(Form1 form)
        {
            this.form = form;
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            form.AddListBox = new object[]
                                  {
                                      textBox1.Text
                                  };
        }
    }
  • Remove From My Forums

 none

Как управлять элементами одной формы из другой?

  • Вопрос

  • К примеру: на форме1 есть BindingNavigator. На форме2 есть кнопка, при нажатии на которую можно было бы управлять BindingNavigator’ом на форме1.

    Типа так:

    BindingNavigator.Enabled = false;

    • Перемещено

      1 октября 2010 г. 21:49
      MSDN Forums consolidation (От:Visual C#)

Ответы

  • Если проблема в том, как иметь доступ изо всех форм ко всем другим формам, то это очень просто — засуньте все формы в контейнер и сделайте ContainerControlledLifetimeManager(). Теперь в любой из форм просто создайте свойство IUnityContainer Container, и
    когда нужен доступ к какой-то форме, просто пишете Container.Resolve<Form2>().

    Это если использовать WinForms. В WPF все немного сложнее.


    — Dmitri Nesteruk

    • Предложено в качестве ответа
      OlegGel
      20 июня 2010 г. 17:49
    • Помечено в качестве ответа
      I.Vorontsov
      21 июня 2010 г. 11:14

В Form1.cs:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent(); 
            frm2 = new Form2();        
        }
        Form2 frm2;

        private void button1_Click(object sender, EventArgs e)
        {
            frm2.Show();
        }
    }

Так как после закрытия формы Form2 она уничтожается, то я переопределяю метод для закрытия — OnClosing. Нужно зайти в конструктор формы Form2. В свойствах формы найти значок с молнией. В списке найти FormClosing и кликнуть дважды на пустое поле справаот него. В редакторе кода появится новый метод, в котором я пишу следующее:

private void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {
        e.Cancel = true;
        Hide();
    }

Далее другой пример, который касается взаимодействия дочерней формы и родительской.
Form1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace childform
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form2 tempDialog = new Form2(this);
            tempDialog.ShowDialog();
        }

        public void msgme()
        {
            MessageBox.Show("Parent Function Called");
        }

    }
}

Form2.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace childform
{
    public partial class Form2 : Form
    {
        private Form1 m_parent;

        public Form2(Form1 frm1)
        {
            InitializeComponent();
            m_parent = frm1;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            m_parent.msgme();
        }
    }
}

В результате должен появиться мессаджбокс с сообщением «Parent Function Called».
Если нужно обратиться к элементу формы, не забываем указывать видимость, так как по умолчанию она Private, то есть элемент не доступен извне. В конструкторе у свойства элемента устанавливаем Modifiers -> Public.

Многие, кто начинал изучение WinForm приложений, сталкивались с проблемой обмена данными между окнами программы. Обмен данными между формами сводится к трем основным принципам: передача параметров в форму, получение данных из формы, изменение значений другой формы. Начнем по порядку.

1) Передача параметров в форму. Любой класс, должен иметь конструктор, и WinForm в этом случае не исключение. А следовательно очевидным является тот факт, что передача данных необходимых для инициализации формы необходимо проводить именно через конструктор формы. Приведем пример.

Создадим WinForm и перейдем к коду. Наблюдаем следующую картину:

public partial class Form1 : Form
    {
        public Form1() // <-- Конструктор формы по умолчанию
        {
            InitializeComponent();
        } }

Допустим на данной форме размещен элемент textBox в который мы хотим установить значение, при открытии нашей формы. Тогда модифицируем наш код следующим образом:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        } 
        public Form1(string text) // <-- Новый конструктор формы
        {
            InitializeComponent();
            textBox.Text = text;
        }
    }

Важно: Все действия, выполняемые с объектами формы должны быть произведены после функции InitializeComponent()!

2-3) По сути задача получения данных из формы и изменение данных в форме сводистя к одной задаче. Пусть у нас есть две формы Form1 и Form2. В первой форме у нас есть три кнопки: open, read, write . Первая откроет вторую форму, в которой есть элемент textBox, Вторая покажет сообщение с текстом, введенным в textBox формы номер два, третья очистит textBox из Form2. Имеем:

public partial class Form1 : Form
    {
        private Form2 F2 = new Form2();
 //<--Объявляем форму два как элемент класса формы один

        public Form1()
        {
            InitializeComponent();
        }
        private void open_Click(object sender, EventArgs e)
        {
            F2.ShowDialog();
        }
        private void read_Click(object sender, EventArgs e)
        {
            MessageBox.Show(F2.textBoxValue);
        }
        private void write_Click(object sender, EventArgs e)
        {
            F2.textBoxValue = String.Empty;
        }
    }

    public partial class Form2 : Form
    {
        public string textBoxValue
//<--Данная конструкция позволяет получить доступ
//к private элементам формы
        {
            get { return textBox.Text; }
            set { textBox.Text = value; }
        }
        public Form2()
        {
            InitializeComponent();
        }
    }

Вот и все. Оказалось не все так сложно 😉

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

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

Но какой-то странный!

Я должен сказать также в VB.Net, хотя наши методы/свойства все еще являются частными, он может быть доступен из других форм/классов, вызывая форму как переменную без каких-либо проблем.

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

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

Или же

Объявите всю форму в статическом классе и статической переменной, и все еще есть внутренний модификатор. Затем, когда вы предполагаете использовать эту форму для показа пользователям, передайте новую конструкцию Form() этому статическому классу/переменной. Теперь он может быть доступен везде, где вы хотите. Но вам все еще нужно что-то еще. Вы также объявляете свой внутренний модификатор элемента в Designer File of Form. Пока ваша форма открыта, она может быть доступна везде. Это может работать для вас очень хорошо.

Рассмотрим этот пример.

Предположим, вы хотите получить доступ к форме TextBox.

Таким образом, первая задача — объявление статической переменной в статическом классе (причина статичности — в простоте доступа без использования новых клавиш в будущем).

Во-вторых, перейдите к классу дизайнеров той формы, которая предполагает доступ к другим формам. Измените объявление модификатора TextBox с частного на внутреннее. Не беспокойся; .Net никогда не изменяет его снова на приватный модификатор после вашего изменения.

В-третьих, когда вы хотите вызвать эту форму для открытия, передайте новую конструкцию формы этому статическому variable— >> статическому классу.

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

Посмотрите на код ниже (у нас есть три объекта. 1- статический класс (в нашем примере мы называем его A)

2 — Любая форма, которая хочет открыть окончательную форму (в нашем примере это FormB).

3 — Реальная Форма, которую нам нужно открыть, и мы предполагаем доступ к ее внутреннему TextBox1 (в нашем примере FormC).

Посмотрите на коды ниже:

internal static class A
{
    internal static FormC FrmC;
}

FormB ...
{
    '(...)
    A.FrmC = new FormC();
    '(...)
}

FormC (Designer File) . . . 
{
     internal System.Windows.Forms.TextBox TextBox1;
}

Вы можете получить доступ к этой статической переменной (здесь FormC) и ее внутреннему контролю (здесь Textbox1) где угодно и когда угодно, пока FormC.


Любой комментарий/идея, дайте мне знать. Я рад услышать от вас или кого-либо еще об этой теме больше. Честно говоря, у меня были некоторые проблемы, связанные с этой проблемой в прошлом. Наилучшим способом было второе решение, которое, я надеюсь, сработает для вас. Дайте мне знать любую новую идею/предложение.

Автор Сообщение
 

СообщениеДобавлено: 10.02.2008 2:25 

на форме1 есть кнопка btn

на форме2 есть listbox

я хочу по нажатию на кнопку btn вывести «Ура заработало» в listbox

объявления типа

public static System.Windows.Forms.ListBox listBox;

выдают ошибку:

Member ‘WindowsFormsApplication1.Form2.listBox’ cannot be accessed with an instance reference; qualify it with a type name instead

Реклама

Партнер
 
sashar2

Member

Статус: Не в сети
Регистрация: 05.12.2005

У компонента listBox ставишь свойство Modifers в положение public.

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

А делать объявление public static для компоненты формы очень некрасиво…

 
eshtrey

sashar2 писал(а):

У компонента listBox ставишь свойство Modifers в положение public.
В конструктор другой формы передаешь указатель на твою Form2. Там уже можешь запомнить этот указатель где-нибудь еще, но главное ты сможешь спокойно из другой формы менять значение твоего listbox.
А делать объявление public static для компоненты формы очень некрасиво…

Всё равно не получается. Возможно я что то не так сделал.

private void button1_Click(object sender, EventArgs e)

{

Form sysForm = new Form2();

//Form2.listBox1.Items.Add(«adf»); — ошибка

//sysForm.listBox1.Items.Add(«adf»); — ошибка

sysForm.Show();

}

компонент listbox1 взят из toolbox

 
sashar2

Member

Статус: Не в сети
Регистрация: 05.12.2005

eshtrey

Конечно не так сделал…

Код:

   

private void button1_Click(object sender, EventArgs e)
    {
      Form2 form2 = new Form2();
      form2.listBox1.Items.Add(«Hello from Form1!»);
      form2.Show();
    }

 
eshtrey

sashar2 писал(а):

eshtrey
Конечно не так сделал…

Код:

   

private void button1_Click(object sender, EventArgs e)
    {
      Form2 form2 = new Form2();
      form2.listBox1.Items.Add(«Hello from Form1!»);
      form2.Show();
    }

Спасибо, заработало!

Я просто ставил Form вместо Form2, глупая ошибка
Добавлено спустя 1 минуту, 4 секунды
А вот второй способ

Form frm = Application.OpenForms[«Form2»];

ListBox lst = (ListBox)frm.Controls[«listBox1»];

lst.Items.Add(«Ура зароботало!»);

 
sashar2

Member

Статус: Не в сети
Регистрация: 05.12.2005

eshtrey

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

Понравилась статья? Поделить с друзьями:
  • Windows forms для visual studio 2019 скачать
  • Windows forms всплывающее окно с вводом данных
  • Windows forms visual studio mac os
  • Windows forms projects with c in visual studio 2019
  • Windows forms how to close window