views:

42

answers:

5

I want to access certain form elements from classes that normally don't have access to them. Allow me to illustrate the problem.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Collections;

namespace MyApp {
    public partial class MyApp : Form
    {
        public MyApp()
        {
            InitializeComponent();

            // Code
        }

        public void updateLabel(string message)
        {
            myLabel.Text = message;
        }
    }

    public class NewClass
    {
        public NewClass()
        {
            // I want to call updateLabel("My message") here, but 'MyApp.updateLabel("My message");' didn't work even though I made updateLabel public
        }
    }
}

How do I tackle this issue? I'm relatively new to C#, but I have experience with C, PHP, Java and JavaScript. I'm using Visual C# 2010 Express.

+1  A: 

You need to pass the instance of the MyApp class to the NewClass class.
You can then call UpdateLabel on the MyApp instance, without making the label public.

SLaks
Is there no other way to access the form element besides letting `NewClass` access the entire `MyApp` class? I'm still a newbie, but that doesn't sound very elegant. Is that a common practice?
Pieter
You can use an interface.
SLaks
A: 

Since updateLabel is a non-static member method in MyApp, you need to create an instance of MyApp before calling any of its instance methods.

use following line of code inside NewClass ctor:

MyApp myapp = new MyApp();
myapp.updateLabel("Hello World");

I assume MyApp class is already instantiated, in which case you have to pass the reference to NewClass (may be over constructor) as SLaks already mentioned.

Liton
A: 

May be technique below will be helpfull. It may use Action's or Func's:

[Test]
        public void ActionsTest()
        {
            var parent = new Parent();
            parent.Child.RaiseCallFromParent();
            parent.Child.RaiseCallInParent();
        }

        public class Parent
        {
            private readonly Child _child = new Child();

            public Parent()
            {
                Child.ActionToCallMethodFromParent = methodCalledFromChild;
                Child.ActionToBeCalledInParent += actionCalledInParent;
            }

            public Child Child
            {
                get { return _child; }
            }

            private void actionCalledInParent()
            {
                Console.WriteLine("It is called in parent on child initiative.");
            }


            private void methodCalledFromChild()
            {
                Console.WriteLine("It is called from child");
            }
        }

        public class Child
        {
            public Action ActionToCallMethodFromParent;
            public Action ActionToBeCalledInParent;

            public void RaiseCallFromParent()
            {
                //This works in cases when you need to consume something from Parent but here you cannot take it directly
                if (ActionToCallMethodFromParent != null)
                    ActionToCallMethodFromParent();
            }

            public void RaiseCallInParent()
            {
                //This works like an event
                if (ActionToBeCalledInParent != null)
                    ActionToBeCalledInParent();
            }
        }
Eugene Cheverda
A: 

Here's my own proposed solution. I pass the myLabel as a parameter to the class constructor that needs access to the label, like so:

The call:

NewClass newClassObj = new NewClass(myLabel);

The class:

public class NewClass
{
    public NewClass(Label myLabel)
    {
        myLabel.Text = "Hello world!";
    }
}

Unless this a bad programming practice, I'd prefer this solution. Thoughts?

Pieter
A: 

Its probably better to raise an event from your own class then catch it in the form and update the controls from there, then you are not connecting your logic to specific UI elements.

Cookey