Лучший способ получить доступ к элементу управления в другой форме в Windows Forms? - PullRequest
47 голосов
/ 12 августа 2008

Во-первых, это вопрос о настольном приложении, использующем Windows Forms, а не ASP.NET .

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

otherForm.Controls["nameOfControl"].Visible = false;

Это не работает так, как я ожидал. Я получаю исключение из Main. Тем не менее, если я сделаю элементы управления public вместо private, я смогу получить к ним прямой доступ, например ...

otherForm.nameOfControl.Visible = false;

Но разве это лучший способ сделать это? Считается ли создание элементов управления public в другой форме «наилучшей практикой»? Есть ли "лучший" способ доступа к элементам управления в другой форме?

Дальнейшее объяснение:

Это на самом деле своего рода продолжение другого вопроса, который я задал, Лучший способ создания интерфейса типа «диалог предпочтений в виде дерева» в C #? . Ответ, который я получил, был замечательным и решил многие, многие организационные проблемы, с которыми я столкнулся в плане обеспечения простоты и легкости работы с пользовательским интерфейсом как во время выполнения, так и во время проектирования. Тем не менее, это подняло эту единственную проблему: легко управлять другими аспектами интерфейса.

По сути, у меня есть корневая форма, которая создает множество других форм, которые находятся на панели в корневой форме. Так, например, переключателю в одной из этих подформ может потребоваться изменить состояние значка строки состояния в основной корневой форме. В этом случае мне нужна субформа для общения с элементом управления в строке состояния родительской (корневой) формы. (Надеюсь, это имеет смысл, а не в стиле «кто на первом»).

Ответы [ 17 ]

37 голосов
/ 12 августа 2008

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

public bool ControlIsVisible
{
     get { return control.Visible; }
     set { control.Visible = value; }
}

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

20 голосов
/ 12 августа 2008

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

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

Надеюсь, это поможет. Возможно, вы могли бы расширить сценарий, если нет?

8 голосов
/ 12 августа 2008

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

Сделать все это также не лучшим способом.

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

public Boolean nameOfControlVisible
{
    get { return this.nameOfControl.Visible; }
    set { this.nameOfControl.Visible = value; }
}

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

otherForm.nameOfControlVisible = true;

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

public ControlType nameOfControlP
{
    get { return this.nameOfControl; }
    set { this.nameOfControl = value; }
}
5 голосов
/ 12 августа 2008

После прочтения дополнительных деталей я согласен с robcthegeek : инициировать событие. Создайте собственный EventArgs и передайте через него необходимые параметры.

3 голосов
/ 31 января 2012

Предположим, у вас есть две формы, и вы хотите скрыть свойство одной формы через другую:

form1 ob = new form1();
ob.Show(this);
this.Enabled= false;

и когда вы хотите вернуть фокус с form1 с помощью кнопки form2, тогда:

Form1 ob = new Form1();
ob.Visible = true;
this.Close();
2 голосов
/ 23 июня 2011
  1. Используйте обработчик событий, чтобы уведомить другую форму, чтобы обработать его.
  2. Создайте открытое свойство в дочерней форме и получите доступ к нему из родительской формы (с действительным приведением).
  3. Создание другого конструктора в дочерней форме для настройки параметров инициализации формы
  4. Создание пользовательских событий и / или использование (статических) классов.

Лучшей практикой будет # 4, если вы используете немодальные формы.

2 голосов
/ 12 августа 2008

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

1 голос
/ 13 мая 2011

С помощью свойства (выделено) я могу получить экземпляр класса MainForm. Но это хорошая практика? Что вы порекомендуете?

Для этого я использую свойство MainFormInstance, которое запускается методом OnLoad.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LightInfocon.Data.LightBaseProvider;
using System.Configuration;

namespace SINJRectifier
{

    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e)
        {
            UserInterface userInterfaceObj = new UserInterface();
            this.chklbBasesList.Items.AddRange(userInterfaceObj.ExtentsList(this.chklbBasesList));
            MainFormInstance.MainFormInstanceSet = this; //Here I get the instance
        }

        private void btnBegin_Click(object sender, EventArgs e)
        {
            Maestro.ConductSymphony();
            ErrorHandling.SetExcecutionIsAllow();
        }
    }

    static class MainFormInstance  //Here I get the instance
    {
        private static MainForm mainFormInstance;

        public static MainForm MainFormInstanceSet { set { mainFormInstance = value; } }

        public static MainForm MainFormInstanceGet { get { return mainFormInstance; } }
    }
}
1 голос
/ 14 апреля 2009

Вы можете

  1. Создать открытый метод с необходимым параметром в дочерней форме и вызвать его из родительской формы (с допустимым приведением)
  2. Создание открытого свойства в дочерней форме и доступ к нему из родительской формы (с действительным приведением)
  3. Создание другого конструктора в дочерней форме для настройки параметров инициализации формы
  4. Создание пользовательских событий и / или использование (статических) классов

Лучшая практика будет # 4, если вы используете немодальные формы.

1 голос
/ 12 августа 2008

Я согласен с использованием событий для этого. Поскольку я подозреваю, что вы создаете MDI-приложение (поскольку вы создаете много дочерних форм) и динамически создаете окна и, возможно, не знаете, когда отписаться от событий, я рекомендую вам взглянуть на Слабые шаблоны событий . Увы, это доступно только для фреймворков 3.0 и 3.5, но что-то похожее может быть реализовано довольно просто со слабыми ссылками.

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

public static Control FindControl(Form form, string name)
{
    foreach (Control control in form.Controls)
    {
        Control result = FindControl(form, control, name);

        if (result != null)
            return result;
    }

    return null;
}

private static Control FindControl(Form form, Control control, string name)
{
    if (control.Name == name) {
        return control;
    }

    foreach (Control subControl in control.Controls)
    {
        Control result = FindControl(form, subControl, name);

        if (result != null)
            return result;
    }

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