-
Dec 8th, 2015, 02:08 PM
#1
Thread Starter
Junior Member
Change User Control associated within a panel from another User Control
In my app, I have three panels that make up the main screen. A header panel, a Navigation panel and a Main display panel.
When user clicks on the navigation button in nav panel, I use the following code to display the proper user control in main panel
Dim tempobject as new [usercontrol]
pnlMain.Controls.Clear()
pnlMain.Controls.Add(tempobject)
If I were to have a user control that contained sub menu items from a button in the nav panel,how would I call a new UC to the pnlMain if I am already in a UC in pnlMain?
Also, how would I create a generic function to accept a usercontrol (one that I want to display in pnlMain) as a parameter and display in pnlMain?
Something like this?
Public Sub GetUserControl(uc as System.Windows.Forms.Control)
Dim tempobject as new uc
pnlMain.Controls.Clear()
pnlMain.Controls.Add(tempobject)
That code isnt working, Getting error "value of type 'uc' cannot be converted to 'System.Windows.Forms.Control'
-
Dec 8th, 2015, 03:10 PM
#2
Re: Change User Control associated within a panel from another User Control
The New keyword means to create a new object of the given type by calling a constructor. But "uc" is a parameter to your Sub. So when you write this line:
Code:
Dim tempobject As New uc()
I'm surprised you aren't being told something like "Unknown type: 'uc'". It implies you probably have some class named "uc" in your program.
So what your sub is doing, as written, is creating a new instance of some class called 'uc', and trying to add it to pnlMain's Controls collection. But whatever 'uc' is, it isn't a Control, so that attempt fails. What I'd expect this method to look like is:
Code:
Public Sub GetUserControl(uc as System.Windows.Forms.Control)
pnlMain.Controls.Clear()
pnlMain.Controls.Add(uc)
End Sub
With respect to your first question, that's a question of application architecture. You could have your UserControls know that their parent is pnlMain, and that IT's parent is some form, and via casts and Parent properties make the appropriate calls. I don't like that.
In this style of application, since you have a concept of navigation, why not make a Navigation class that knows about pnlMain and is referenced by your UserControls. That way, when they want to update the control in pnlMain, they talk to the Navigation class. Here's about as quick and dirty as that gets:
Code:
Public Class Form1
Private _pnlMain As New Panel()
Private _navigation As Navigation
Public Sub New()
InitializeComponent()
_pnlMain = New Panel()
_pnlMain.Dock = DockStyle.Fill
Controls.Add(_pnlMain)
_navigation = New Navigation(_pnlMain)
Dim startControl = New FirstUserControl(_navigation)
_navigation.SetNewControl(startControl)
End Sub
End Class
Public Class FirstUserControl
Inherits UserControl
Private _navigation As Navigation
Public Sub New(ByVal navigation As Navigation)
_navigation = navigation
BackColor = Color.Crimson
Dock = DockStyle.Fill
Dim btn As New Button() With {.Text = "1"}
AddHandler btn.Click, AddressOf HandleClick
Me.Controls.Add(btn)
End Sub
Private Sub HandleClick(sender As Object, e As EventArgs)
_navigation.SetNewControl(New SecondUserControl(_navigation))
End Sub
End Class
Public Class SecondUserControl
Inherits UserControl
Private _navigation As Navigation
Public Sub New(ByVal navigation As Navigation)
_navigation = navigation
BackColor = Color.Azure
Dock = DockStyle.Fill
Dim btn As New Button() With {.Text = "2"}
AddHandler btn.Click, AddressOf HandleClick
Me.Controls.Add(btn)
End Sub
Private Sub HandleClick(sender As Object, e As EventArgs)
_navigation.SetNewControl(New FirstUserControl(_navigation))
End Sub
End Class
Public Class Navigation
Private _container As Panel
Public Sub New(ByVal container As Panel)
_container = container
End Sub
Public Sub SetNewControl(ByVal uc As UserControl)
_container.Controls.Clear()
_container.Controls.Add(uc)
End Sub
End Class
There's a lot going on, but walk through it. The form creates a Navigation instance after it creates its Panel, and that class is responsible for updating the Panel's children. Each UserControl expects to get that Navigation instance, and will use it to create the next UI when its button is clicked. And it doesn't matter if it's a sub-menu, or even a child control: so long as what you're working with has a reference to that one Navigation object, it can update the UI.
There's a lot of features you could add, but this should be a nudge in the right direction.
(You also probably want to Dispose() of controls instead of just calling Clear() on the panel, but the timing on that's tricky.)
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
Dec 8th, 2015, 03:48 PM
#3
Thread Starter
Junior Member
Re: Change User Control associated within a panel from another User Control
Originally Posted by Sitten Spynne
The New keyword means to create a new object of the given type by calling a constructor. But "uc" is a parameter to your Sub. So when you write this line:
Code:
Dim tempobject As New uc()
I'm surprised you aren't being told something like "Unknown type: 'uc'". It implies you probably have some class named "uc" in your program.
So what your sub is doing, as written, is creating a new instance of some class called 'uc', and trying to add it to pnlMain's Controls collection. But whatever 'uc' is, it isn't a Control, so that attempt fails. What I'd expect this method to look like is:
Code:
Public Sub GetUserControl(uc as System.Windows.Forms.Control)
pnlMain.Controls.Clear()
pnlMain.Controls.Add(uc)
End Sub
With respect to your first question, that's a question of application architecture. You could have your UserControls know that their parent is pnlMain, and that IT's parent is some form, and via casts and Parent properties make the appropriate calls. I don't like that.
In this style of application, since you have a concept of navigation, why not make a Navigation class that knows about pnlMain and is referenced by your UserControls. That way, when they want to update the control in pnlMain, they talk to the Navigation class. Here's about as quick and dirty as that gets:
Code:
Public Class Form1
Private _pnlMain As New Panel()
Private _navigation As Navigation
Public Sub New()
InitializeComponent()
_pnlMain = New Panel()
_pnlMain.Dock = DockStyle.Fill
Controls.Add(_pnlMain)
_navigation = New Navigation(_pnlMain)
Dim startControl = New FirstUserControl(_navigation)
_navigation.SetNewControl(startControl)
End Sub
End Class
Public Class FirstUserControl
Inherits UserControl
Private _navigation As Navigation
Public Sub New(ByVal navigation As Navigation)
_navigation = navigation
BackColor = Color.Crimson
Dock = DockStyle.Fill
Dim btn As New Button() With {.Text = "1"}
AddHandler btn.Click, AddressOf HandleClick
Me.Controls.Add(btn)
End Sub
Private Sub HandleClick(sender As Object, e As EventArgs)
_navigation.SetNewControl(New SecondUserControl(_navigation))
End Sub
End Class
Public Class SecondUserControl
Inherits UserControl
Private _navigation As Navigation
Public Sub New(ByVal navigation As Navigation)
_navigation = navigation
BackColor = Color.Azure
Dock = DockStyle.Fill
Dim btn As New Button() With {.Text = "2"}
AddHandler btn.Click, AddressOf HandleClick
Me.Controls.Add(btn)
End Sub
Private Sub HandleClick(sender As Object, e As EventArgs)
_navigation.SetNewControl(New FirstUserControl(_navigation))
End Sub
End Class
Public Class Navigation
Private _container As Panel
Public Sub New(ByVal container As Panel)
_container = container
End Sub
Public Sub SetNewControl(ByVal uc As UserControl)
_container.Controls.Clear()
_container.Controls.Add(uc)
End Sub
End Class
There's a lot going on, but walk through it. The form creates a Navigation instance after it creates its Panel, and that class is responsible for updating the Panel's children. Each UserControl expects to get that Navigation instance, and will use it to create the next UI when its button is clicked. And it doesn't matter if it's a sub-menu, or even a child control: so long as what you're working with has a reference to that one Navigation object, it can update the UI.
There's a lot of features you could add, but this should be a nudge in the right direction.
(You also probably want to Dispose() of controls instead of just calling Clear() on the panel, but the timing on that's tricky.)
So in your example, the "Form" would be my main form that has the panels on it, and the FirstUserControl, SecondUserControl, etc are the user controls that would be shown in pnlMain?
-
Dec 8th, 2015, 04:11 PM
#4
Re: Change User Control associated within a panel from another User Control
Yep. It's just organized a little weird because no one would toss them all in one file like this, and I'm not using the designer at all. That wasn't for a technical reason, it's just easier to post that kind of project on the forums.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
Dec 8th, 2015, 05:09 PM
#5
Thread Starter
Junior Member
Re: Change User Control associated within a panel from another User Control
Originally Posted by Sitten Spynne
Yep. It's just organized a little weird because no one would toss them all in one file like this, and I'm not using the designer at all. That wasn't for a technical reason, it's just easier to post that kind of project on the forums.
I'll take a stab at implementation and let you know how it goes
-
Dec 8th, 2015, 06:25 PM
#6
Thread Starter
Junior Member
Re: Change User Control associated within a panel from another User Control
I put the code in a new project and was able to see how the code works. Pretty sweet. My question is, if I want to have my panels outlines as follows:
Would I just create the panel on frmMain with dimensions on New Panel()? Same with navigation when adding buttons? Could the panels and navigation buttons be done at design time and i reference when showing in pnlMain? My second level of navigation buttons would be in a UC in pnlMain
-
Dec 8th, 2015, 08:55 PM
#7
Re: Change User Control associated within a panel from another User Control
You don't have to make the Panel yourself like I did, you can use the designer if you wish, and that's usually an easier way to get it sized right. But I do like Sub New() for setting up other things. There's just one trick to using it with the designer.
If you type out Sub New(), Visual Studio is likely to replace it with this:
Code:
Public Sub New()
' Some really long comment
InitializeComponent()
' Another really long comment
End Sub
InitializeComponent() is where all your designer controls get made. So if you put your code before that, all your controls will be Nothing at the time and you'll be sad to get NullReferenceExceptions. The solution's easy: if you want to do stuff in Sub New(), make sure it goes after InitializeComponent() so all your designer controls are set up.
You could also use the Load or Shown events, but I prefer to put things in the constructor.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|