Основы применения Windows Forms: хранение всех форм в одном окне

1

Я пишу приложение Windows Forms в VB.net с помощью Visual Studio 2010 (ответы С# по-прежнему приветствуются).

Я создал функциональность моего приложения, и теперь я работаю над потоком пользовательского интерфейса. В принципе, мне нужно сделать все функциональные возможности для приложения, которые появляются/исчезают с самого начала, вводная форма. Они нажимают на один из вариантов в форме Introduction.vb, и исходный материал исчезает и заменяется тем, на что он нажал. Затем на следующей странице появляется кнопка "Назад", если они хотят вернуться к предыдущей странице. Вот оригинал Introduction.vb:

Public Class Introduction
Inherits System.Windows.Forms.Form
Private Sub Introduction_Load(sender As System.Object, e As System.EventArgs) Handles Me.Load
End Sub

Private Sub AddOrRemoveButton_Click(sender As System.Object, e As System.EventArgs) Handles AddOrRemoveButton.Click
    AddRemoveCompany.Show() '<-- Show the AddRemoveCompany.vb form when they click on the button.
End Sub

Private Sub InvoiceDocumentButton_Click(sender As System.Object, e As System.EventArgs) Handles InvoiceDocumentButton.Click
    InvoicePrinterAndDocCreator.Show() '<-- .vb form
End Sub 

Private Sub LockOrUnlockButton_Click(sender As System.Object, e As System.EventArgs) Handles LockOrUnlockButton.Click
    LockUnlockPIN.Show() '<-- .vb form
End Sub

Private Sub ToExcelButton_Click(sender As System.Object, e As System.EventArgs) Handles ToExcelButton.Click
    ToExcel.Show() '<-- .vb form
End Sub
End Class

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

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

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

Позвольте мне опубликовать (один из), что я пробовал, что на самом деле работает:

Public Class MainForm
Private Sub MainForm_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    Dim x = New Introduction
    Me.Controls.Add(x)
    x.Show()
End Sub
End Class

Этот MainForm, конечно же, заменяет старую форму Introduction.vb и вместо этого отображает UserControl Introduction.vb. Вот новый элемент управления UserControl.

Public Class Introduction
Inherits System.Windows.Forms.UserControl
Private Sub Introduction_Load(sender As System.Object, e As System.EventArgs) Handles Me.Load
End Sub

Private Sub AddOrRemoveButton_Click(sender As System.Object, e As System.EventArgs) Handles AddOrRemoveButton.Click
    ' Testing logic here:
    Dim y = New AddRemoveCompany '<-- One of my old forms that was converted to a UserControl.
    MainForm.Controls.Clear()
    MainForm.Controls.Add(y)
    y.Show()
End Sub

Private Sub InvoiceDocumentButton_Click(sender As System.Object, e As System.EventArgs) Handles InvoiceDocumentButton.Click
    InvoicePrinterAndDocCreator.Show() '<-- Still works, but still opens in a new window
End Sub

Private Sub LockOrUnlockButton_Click(sender As System.Object, e As System.EventArgs) Handles LockOrUnlockButton.Click
    LockUnlockPIN.Show()
End Sub

Private Sub TRSToExcelButton_Click(sender As System.Object, e As System.EventArgs) Handles TRSToExcelButton.Click
    TRSToExcel.Show()
End Sub
End Class

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

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

Теги:
forms

3 ответа

3
Лучший ответ

Есть сотни способов сделать это: нужно установить свойство TopLevel вашей формы в false. Или ваш MainForm должен содержать панель, в которой вы можете загружать UserControls динамически.

В основном вы ищете концепцию Composite UI. Большинство приложений Composite UI в.NET. Используйте WPF, как лучше подходит (imho). Но для WinForms существуют довольно простые понятия. (Как уже упоминалось выше, создайте панель и динамически загружайте UserControls в нее).

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

Например:

public void button_Click(object sender, EventArgs e)
        {
            this.panelBoarder.Controls.Clear() //Hide old content

            if (this.pageTwo == null)
                this.pageTwo = new PageTwo(); // Create Page Two

            this.panelBoarder.Controls.Add(this.pageTwo);
            this.pageTwo.Visible = true;
        }
  • 0
    Не могли бы вы подробнее рассказать об этом? Я также нашел это в своих исследованиях в Интернете, но не смог реализовать это должным образом ... Я бы в основном добавил / удалил формы, как я делал выше, но в коллекцию MainPanel.Controls, а не прямо в MainForm.Controls. коллекция
  • 1
    Что вы не хотите знать, это довольно простая задача
Показать ещё 9 комментариев
1

Лично я не поклонник изменения коллекции Controls по нескольким причинам:

  • Там много повторного рисования, которое выполняется без необходимости (декомпилируйте ControlsCollection.Add и посмотрите)
  • Вы будете возиться с z-порядком
  • Мне никогда не приходилось делать это для выполнения задач, связанных с пользовательским интерфейсом, и то, что вы описали выше, можно сделать без модификации элементов управления
    • Будь проще :)

Вот пример, который я думаю, о котором вы просите.

Он использует TabPage (без заголовков) для размещения элементов управления (я добавил метки, обозначающие "страницу", но так же легко можно было бы контролировать ваши пользователи). Кнопка "Назад" обрабатывается Stack так как это то, что вы ищете for-, нажимая новые параметры страницы и выталкивая их, когда пользователь хочет вернуться:

public partial class Form1 : Form
{
    //...
    Stack<TabPage> breadCrumbs = new Stack<TabPage>();

    private void SwitchTabs(TabPage page)
    {
        breadCrumbs.Push(tabControl1.SelectedTab);
        tabControl1.SelectedTab = page;
    }

    //...

    //Go back
    private void toolStripButton1_Click(object sender, EventArgs e)
    {
        if(breadCrumbs.Count == 0)
            return;

        var lastTab = breadCrumbs.Pop();
        tabControl1.SelectedTab = lastTab;
    }
}

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

1

Вот хороший пример. Это предполагает, что ваша форма имеет панель на панели Panel1, а форма, которую вы хотите отобразить на этой панели, - Form2:

Dim f2 As New Form2
f2.TopLevel = False
f2.ControlBox = False
f2.FormBorderStyle = Windows.Forms.FormBorderStyle.None
Panel1.Controls.Add(f2)
f2.Show()

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню