[C# Winforms] static/non-static confusion

Associate
Joined
3 Jan 2006
Posts
522
Location
The Undercroft
Feeling really thick at the moment as I just cant work out how to get this working:

I'm developing a simple C# .NET WinForm database front-end app which consists of a main form (we'll call 'MainForm' for now), a Panel control on MainForm, and 3 usercontrols (CtrlA, CtrlB, CtrlC). When the app is started the 3 usercontrols are added to the panels control collection and i'm changing the .visible properly of the usercontrols, using menu buttons on MainForm, so only 1 is visible at a time.

So far its working fine except now I need a method in CtrlA to pass a variable to a public method on MainForm, which hides CtrlA, makes CtrlC visible then passes the variable into a method in CtrlC which then accesses the database and changes the properties of a bunch on controls on CtrlC.

The problem is I can only access the public methods if they are static, and if they are static I can't set properties etc so whats the normal way of getting the usercontrols to communicate with each other properly? I've been looking at delegates and googling all sorts but I just cant get my head around it all :confused: :o
Up till now i've only worked with ASP.NET web apps, this is my first forms project for a LONG time so step by step explinations would be a great help <3
 
Trimmed codebehind for main form:
Code:
namespace DDatabase
{
    public partial class frmDdb : Form
    {
        private ctrlCalendar calCtrl = new ctrlCalendar();
        private ctrlNewPatient newPatientCtrl = new ctrlNewPatient();
        private ctrlManagePatient manPatientCtrl = new ctrlManagePatient();

        public frmDdb()
        {
          InitializeComponent();
          //controls get added to panel control collection here
          .
        }
          .
          .
        public void Search(string strPatientID)
        {
            pnlContainer.Controls[0].Visible = false;
            pnlContainer.Controls[2].Visible = true;
            //need to access ctrlManagePatient SearchPatient(strPatientID) method here
        }
    }
}

Trimmed codebehind for ctrlCalendar (CtrlA):
Code:
namespace DDatabase
{
    public partial class ctrlCalendar : UserControl
    {
.
.
         private void dgPatients_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 0)
            {
                string dNumber = dgPatients[e.ColumnIndex, e.RowIndex].Value.ToString();
                //Need to access frmDafneDB Search(dNumber) method here
            }
        }
    }
}

Trimmed codebehind for ctrlManagePatient (CtrlC):
Code:
namespace DDatabase
{
    public partial class ctrlManagePatient : UserControl
    {
     .
     .
     public void SearchPatient(string searchStr)
        {
           //code to access DB and populate controls
        }
    }
}

I havent bothered included code i've tried as I tried lots of different things but based on what I have posted what would you add to make it work?
 
Last edited:
If I do:
CtrlA
Code:
 private void dgPatients_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 0)
            {
                string dNumber = dgPatients[e.ColumnIndex, e.RowIndex].Value.ToString();
                frmDdb.Search(dNumber);
            }
        }

MainForm
Code:
public static void Search(string strPatient)
        {
            frmDdb formDB = new frmDdb();
            formDB.pnlContainer.Controls[0].Visible = false;
            formDB.pnlContainer.Controls[2].Visible = true;
        }

It wont work because i'm referencing a new instance of the form controls, not the actuall visible controls, right?

Code:
public static void Search(string strPatient)
        {
            pnlContainer.Controls[0].Visible = false;
            pnlContainer.Controls[2].Visible = true;
        }
throws error "An object reference is required for the nonstatic field, method, or property 'DDatabase.frmDdb.pnlContainer'
 
the whole file is autogenerated
Code:
namespace DDatabase
{
    partial class frmDdb
    {
....
        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmDafnedb));
            this.linkLabel1 = new System.Windows.Forms.LinkLabel();
            this.linkLabel2 = new System.Windows.Forms.LinkLabel();
            this.linkLabel3 = new System.Windows.Forms.LinkLabel();
            this.pnlContainer = new System.Windows.Forms.Panel();
            this.pnlNav = new System.Windows.Forms.Panel();
            this.pnlNav.SuspendLayout();
            this.SuspendLayout();
            .
            .
            //rest is just setting properties
          }
        private System.Windows.Forms.LinkLabel linkLabel1;
        private System.Windows.Forms.LinkLabel linkLabel2;
        private System.Windows.Forms.LinkLabel linkLabel3;
        private System.Windows.Forms.Panel pnlContainer;
        private System.Windows.Forms.Panel pnlNav;
    }
}
 
Think I might be starting to see why its going wrong..something to do with creating new instances of the usecontrols and adding them during runtime or something?!
How should I be adding usercontrols to the form? I'm used to pretty much dragging and dropping with asp.net
 
Any chance you can post the whole thing up to have a look? It's hard to tell exactly what's going on with the fragments there so far.

I'm a little confused about the way you are going about things.
You shouldn't need to create an instance of the form in a static method, the generated code should handle all of this for what you want.


EDIT: Reading through again it seems you just want to callback to the main form from the user controls.
If so, I've attached a solution that demonstrates how to do it in a few different ways:
Link

Hopefully that's the sort of thing you're after, any problems let me know.
BTW, it's compiled against .NET 3.5 - if you don't have this you can probably just remove the references to the System.Linq libraries and it should work.
 
Last edited:
Yup thats exactly what I need, thanks Haircut.
As I thought, I was being thick and totally confused myself :P
 
Obviously this issue isn't limited to forms. If you want to call a non-static method on any object, you're going to have to have access to a reference to that object :)

Haircut's is the right way to do it, but controls do know their container relationships, so you could attempt it in a cheesy fashion with no prior setup by walking up the Control.Parent hierarchy.

(untested - from the usercontrol)
Code:
Control parent = this.Parent;
while (parent != null)
{
	frmDdb mainForm = parent as frmDdb;
	if (mainForm != null)
	{
		mainForm.Search("jackson");
		break;
	}
	parent = parent.Parent;
}
 
Last edited:
Back
Top Bottom