Link to home
Start Free TrialLog in
Avatar of asp316
asp316

asked on

Communication between UserControls and Winforms

Hi - I have 2 questions:

1. I have a winform application that I have main form containing a treeview on the left and a panel on the right. Based on the treeview node selected. I load a usercontrol into a panel on the right hand side. I want certain user controls to be able to a ) load & show a different user control while passing params to it, and b) unload itself. How do I do this? I thought I could call a shared method on the main form. However, it doesn't appear in intellisense.

2). I come from a web background and am used to masterpages. I want my winform app to feel the same and inherit graphics and layout from the main form. Is the above way a good way to do this? Is there a better way?
Avatar of rambovn
rambovn
Flag of Germany image

1. Use properties in Control
2. Use WPF.
Avatar of asp316
asp316

ASKER

I'd like to use WPF but I don't want to upgrade the clients to .Net 3.x yet. If WPF isn't an option, is this a good way to do it or is there a better?

I'm new to delegates and tried for a while but see only usercontrol to usercontrol communication. I'm looking for the user control to communicate back to the form it's hosted on.

Let me explain further:

frmMain is the main winform. uctl_ContractFind is the usercontrol in a panel on frmMain. When a user selects a contractID on uctl_ContractFind, I want uctl_ContractFind to invoke a method ShowScreen(screenName, parameter) to pass the contractID to frmMain and to know which screen to load up next. frmMain will then unload uctl_ContracFind, load the contract editing usercontrol (uctl_ContractView) into the same panel with the contract information preloaded.

Based on the reading, a delegate would be an appropriate way to do this, ragi0017. However,  I can't get it to work and am not exactly sure where to put all of the code.

rambovn, how would I do this using Control?

Thoughts?
create a delegate and an event in uctl_ContractFind

public delegate void SearchDelegate (string screenName, string parameter);
public event SearchDelegate SearchEvent;

When the user has selected the contract (you know what event fires for this) write the following code
if (SearchEvent != null)
{
     SearchEvent ();
}

in the main form subscribe to the event as (just an idea)
this.uctl_ContractFind1.SearchEvent += new uctl_ContractFind.SearchDelegate(ShowScreen);

this will call your function and then you can handle your cases accordingly
Avatar of asp316

ASKER

thanks. I'm really close.  When I try to compile, in frmMain, in the ( of where you declare the method name invoked by the delegate, I get an error 'Invalid token'.

Ideas?

After some research, an alternate way to do this is  (but I can't get it to work):

//in the uctl_contract_find
frmMain.ChangeScreen screenChange = new frmMain.ChangeScreen(ShowScreen);
screenChange("screenname", "parameter value");

//in frmMain
  public delegate void ChangeScreen(string screenName, string parameter);


the problem with this way is in uctl_contract_find, the (ShowScreen) method errors saying 'ShowScreen' doesn't exist in teh current context.

thoughts on either way?

 
i cannot comment on this way cause the way i had recommended you is already working for me.

BTW what is ChangeScreen - a delegate but on what condition you are calling the delegate (event to be precise)
Sorry for making you wait.
In your code:


//in the uctl_contract_find
frmMain.ChangeScreen screenChange = new frmMain.ChangeScreen(ShowScreen);
screenChange("screenname", "parameter value");

//in frmMain
  public delegate void ChangeScreen(string screenName, string parameter);


You means that you can access frmMain from uctl_contract_find . Good. So, just declare screen as  public in frmMain, then use in uctl_contract_find like this :

frmMain.screen= "new value here";
by the way of events and delegates i mean that if the main form has subscribed to the event in the child form and if the event is triggered from the child form then the control will come to the main form from the child form and after completion of the function will agian go back to the child form.

its just a way to call the function on the main form from the child form when some event happens - in your case update data on the main form
Avatar of asp316

ASKER

rambovn - ShowScreen is public in frmMain and I still get the error in the usercontrol 'ShowScreen does not exist in the current context'.
 
Ragi007 - I'm working with both scenarios, yours and the other so I understand you can't comment on the other approach. I'm calling the delegate in the usercontrol uctl_ContractFind. There's just a button_click event that's invoking the delegate. So, what your saying on how control comes back to the user control after invoking the delegate, I probably should unload the control at that time. Thoughts on the error I'm seeing when I try your suggestion?
can you show me the code of ShowScreen  and where you call it?
Avatar of asp316

ASKER

Sure. Attached is the showscreen method and where I invoke it. It's in frmMain. I call it inside of frmMain for screen changes but what I'm trying to do is call it from uctl_ContractFind as well.
//in frmMain
        
        public void ShowScreen(string screenName,string parameter)
        {
            switch (screenName)
            {
                case "nodContractCreate":
                    strCurrentNodeSelected = "nodContractCreate";
                    UserControl uContract = new Contract.uctl_Contract();
                    pnlShared.Show();
                    pnlShared.Controls.Add(uContract);
 
                    break;
                case "nodQuoteCreate":
                    UserControl uQuote = new Quote.uctl_Quote();
                    pnlShared.Show();
                    pnlShared.Controls.Add(uQuote);
                    strCurrentNodeSelected = "nodQuoteCreate";
                    break;
                case "nodAdminVehicleCategory":
                    UserControl uCat = new Admin.uctl_Vehicle_Category();
                    pnlShared.Show();
                    pnlShared.Controls.Add(uCat);
                    strCurrentNodeSelected = "nodAdminVehicleCategory";
                    break;
                case "nodContractFind":
                    UserControl uQuoteFind = new Contract.uctl_Contract_Find();
                    pnlShared.Show();
                    pnlShared.Controls.Add(uQuoteFind);
                    strCurrentNodeSelected = "nodContractFind";
                    break;
                case "nodClientAdd":
                    UserControl uClientAdd = new Client.uctl_ClientAdd();
                    pnlShared.Show();
                    pnlShared.Controls.Add(uClientAdd);
                    strCurrentNodeSelected = "nodClientAdd";
                    break;
                case "nodDriverAdd":
                    UserControl uDriverAdd = new Drivers.uctl_Drivers_Add();
                    pnlShared.Show();
                    pnlShared.Controls.Add(uDriverAdd);
                    strCurrentNodeSelected = "nodDriverAdd";
                    break;
 
                case "nodVehicleMaintenance":
                    UserControl uVehicleMaintenance = new Vehicles.uctl_Vehicle_Maintenance();
                    pnlShared.Show();
                    pnlShared.Controls.Add(uVehicleMaintenance);
                    strCurrentNodeSelected = "nodVehicleMaintenance";
                    break;
 
                case "nodFleetGlance":
                    strCurrentNodeSelected = "nodFleetGlance";
                    //show form
                    AdvancedFleetManager.frmViewSchedule frmSched = new frmViewSchedule();
                    frmSched.Show();
                    break;
                default:
                    HideAllPanels();
                    //do something different
                    break;
            }
 
            return;
        }
 
 
 
//In uctl_ContractFind, here's where I invoke it:
 
frmMain.ChangeScreen screenChange = new frmMain.ChangeScreen(ShowScreen);
 
screenChange("screenname", "parameter value");

Open in new window

sorry but when you say u r trying my approach i cannot see any way your are subscribing to the event by using the += symbol or i am not able to decipher your code

can you put that code again where u subscribe to the event becuase just using the delegate wont help in this case
Avatar of asp316

ASKER

ragi0017 -

When I use your code, here's the code I use. It should match up with your code. Can you confirm?
in frmMain:
 
 Contract.uctl_Contract_Find.ContractSearchEventDelegate += new Contract.uctl_Contract_Find.ContractSearchEventDelegate(ShowScreen);
       
 
 
in uctl_ContractFind, this is the a button_click event:
 
 
        public delegate void ContractSearchEventDelegate(string screenName, string parameter);
        public event ContractSearchEventDelegate SearchEvent;
 
 
 
 
  private void btnTest_Click(object sender, EventArgs e)
        {
 
             if (SearchEvent != null)
            {
                //  raise an event that goes thru the deleate to change the page
 
                SearchEvent("nodContract", "");
            }
 
        }

Open in new window

looks familiar but just want to confirm again
are these 2 lines in the class (not in the function as mentioned by you)

public delegate void ContractSearchEventDelegate(string screenName, string parameter);
public event ContractSearchEventDelegate SearchEvent;

if this is the case then can you please let me know is the code compiling ok or you getting compile time errors or run time errors
Avatar of asp316

ASKER

Correct. They're in the class and not in the method. I get the error when I try to compile.
can you just explain whats the error as i just did my code and was able to successfully call the event and eventually the registered function for that delegate
Avatar of asp316

ASKER

I get 3 errors :

Invalid token in '+=' in class, struct or interface member declaration
Invalid token in '(' in class, struct or interface member declaration
Invalid token in ')' in class, struct or interface member declaration
ASKER CERTIFIED SOLUTION
Avatar of Anurag Thakur
Anurag Thakur
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of asp316

ASKER

Sorry for the delay. I did exactly as you have above. Everything looks fine when when I try to compile,  in the line below:

 testusercontrol.SearchEvent += new WebUserControl.ContractSearchEventDelegate (testusercontrol_SearchEvent);

the  testusercontrol.SearchEvent is showing 'An object referenced is required for the non-static field, method or property 'AFM.frmViewSchedule.SearchEvent'. You're really close!! I think that if I can get it to subscribe to the event, we got it.


sorry its been a long time back
can you share your code like i have done because i remember mine was working perfectly so thats why i want to have a look at your code which is producing the exception
Avatar of asp316

ASKER

ragi0017,

Thanks for the help. I ended up using just using the event you gave and bubbling that up to the parent form. When I created an instance of the child control, I subscribed the parent to the child's event. I passed the params of the event by use of a global variable because I could't figure out how to use the eventargs object. I'm sure it's not the best way but it seems to work fine.

Thanks again for the help!
//in child control:
 
     //event handler for changing screens
        public event EventHandler evtChangeScreen;
        protected virtual void ChangeScreen(EventArgs e)
        {
            EventHandler Handler = evtChangeScreen;
            if (Handler != null)
                Handler(this, e);
        }
 
 
//in child control where I want to invoke the event
  clsGlobals.gstrChangeScreen_Param = RecordID.ToString();
  ChangeScreen(EventArgs.Empty );
 
 
//in the parent form:
//subscribe to the event and display the form
frmSched.evtChangeScreen += new EventHandler(EventHandler_ChangeScreen);
                    frmSched.Owner = this; 
                    frmSched.ShowDialog();
 
                       
//define the event handler in the parent form
      // The handler for the child form's ChangeScreen event.
        void EventHandler_ChangeScreen(object sender, EventArgs  e)
        {
            ShowScreen(clsGlobals.gstrChangeScreen_ScreenName,clsGlobals.gstrChangeScreen_Param);
         
        }

Open in new window

Avatar of asp316

ASKER

For some reason I couldn't get it to work. Thanks again for the help!!!