Лучший способ получить доступ к элементу управления в другой форме в 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 ]

0 голосов
/ 29 июня 2011

Шаг 1:

string regno, exm, brd, cleg, strm, mrks, inyear;

protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
    string url;
    regno = GridView1.Rows[e.NewEditIndex].Cells[1].Text;
    exm = GridView1.Rows[e.NewEditIndex].Cells[2].Text;
    brd = GridView1.Rows[e.NewEditIndex].Cells[3].Text;
    cleg = GridView1.Rows[e.NewEditIndex].Cells[4].Text;
    strm = GridView1.Rows[e.NewEditIndex].Cells[5].Text;
    mrks = GridView1.Rows[e.NewEditIndex].Cells[6].Text;
    inyear = GridView1.Rows[e.NewEditIndex].Cells[7].Text;

    url = "academicinfo.aspx?regno=" + regno + ", " + exm + ", " + brd + ", " +
          cleg + ", " + strm + ", " + mrks + ", " + inyear;
    Response.Redirect(url);
}

Шаг 2:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        string prm_string = Convert.ToString(Request.QueryString["regno"]);

        if (prm_string != null)
        {
            string[] words = prm_string.Split(',');
            txt_regno.Text = words[0];
            txt_board.Text = words[2];
            txt_college.Text = words[3];
        }
    }
}
0 голосов
/ 07 сентября 2008

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

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

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

@ Ларс, хороший звонок по раздаче ссылок на Форму, я тоже это видел. Насти. Никогда не видел, чтобы они передавали их в слой BLL! Это даже не имеет смысла! Это могло серьезно повлиять на производительность, верно? Если где-то в BLL ссылка будет сохранена, форма останется в памяти, верно?

У вас есть мое сочувствие! ;)


@ Ed, RE ваш комментарий о создании Forms UserControls. Дилан уже указал, что корневая форма создает множество дочерних форм, создавая впечатление приложения MDI (где я предполагаю, что пользователи могут захотеть закрыть различные формы). Если я прав в этом предположении, я думаю, что их лучше всего хранить в форме. Конечно, открыты для исправления:)

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

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

@ Ларс: Вы здесь. Это было то, что я делал в мои первые дни, и с тех пор мне не приходилось делать это, поэтому я сначала предложил вызвать событие, но мой другой метод действительно нарушил бы любое подобие инкапсуляции.

@ Роб: Да, звучит примерно так :). 0/2 на этом ...

0 голосов
/ 17 августа 2016

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

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

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

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

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

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

или

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

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

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

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

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

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

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

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

2 - Любая другая форма, которая хочет открыть окончательную форму (в нашем примере это TextBox 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 открыто.


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

0 голосов
/ 24 мая 2017
public void Enable_Usercontrol1()
{
    UserControl1 usercontrol1 = new UserControl1();
    usercontrol1.Enabled = true;
} 
/*
    Put this Anywhere in your Form and Call it by Enable_Usercontrol1();
    Also, Make sure the Usercontrol1 Modifiers is Set to Protected Internal
*/
0 голосов
/ 17 августа 2008

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

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

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

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

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

  2. Вы можете написать отдельный набор для этой проверки, правильно ли подключена кнопка «Сохранить» к предикату «можно сохранить» (как бы это ни было для вашей платформы, в Cocoa в Mac OS X это часто бывает через переплет).

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

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