I am new to C# and OOP and have researched many of the similar topics but end up more confused than when I started. I need to be able to call a method in a parent class from a child in another namespace.
Below is a (over) simplified example of what I have now and seems to work, but is this the right/best way?
File Form1.cs:
namespace Test1
{
public partial class Form1 : Form
{
NotTest1.Class1 myClass1 = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Start the child class and pass this parent
myClass1 = new NotTest1.Class1(this);
}
public void Form1Function(String text)
{
textBox1.AppendText(text + Environment.NewLine);
}
private void button1_Click(object sender, EventArgs e)
{
// Do some stuff then call Function1 in myClass1
myClass1.Function1();
}
}
}
File Class1.cs:
namespace NotTest1
{
class Class1 {
Test1.Form1 _parent;
public Class1(Test1.Form1 parent) {
_parent = parent;
}
public void Function1()
{
// Do lots of "stuff"
_parent.Form1Function("Got Here");
}
}
}
Examples appreciated, as I am still trying to learn all of the correct terminology.
Thanks
The best way in Class1.cs use using.
using Test1;
namespace NotTest1
{
class Class1 {
Form1 _parent;
public Class1(Form1 parent) {
_parent = parent;
}
public void Function1()
{
// Do lots of "stuff"
_parent.Form1Function("Got Here");
}
}
}
If Class1 needs to call methods on a Form1 instance, then what you have done is perfectly fine, though I don't see how you have parent and child classes here. What you really a Class1 class that happens to accept a Form1 instance in order to call methods on it.
What you did works fine.
Nonetheless, you may want to explore a bit on Events - this way your Parent class may instantiate a child class and subscribe to its events, and your child class may be completely decoupled from your Parent class.
A very nice, clear example is shown on this thread:
Super-simple example of C# observer/observable with delegates
Related
My problem is, I can't invoke a message into the TextBox and I can't understand why.
There is a main class and a second class, both with call to the other one.
Where is my error?
using System;
using System.Windows.Forms;
namespace Class_Test___Invoke
{
public partial class MAINFORM : Form
{
public MAINFORM()
{
InitializeComponent();
_INVOKER = this;
}
private MAINFORM _INVOKER;
private static CLASS _CLASS = new CLASS();
private void button1_Click(object sender, EventArgs e)
{
_CLASS._MESSENGER();
}
public void _LOGGING(string _MESSAGE)
{
if (InvokeRequired)
{
_INVOKER.Invoke(new Action<string>(_LOGGING), new object[] { _MESSAGE });
textBox_ausgabe.AppendText(_MESSAGE);
return;
}
else textBox_ausgabe.AppendText(_MESSAGE);
}
}
}
namespace Class_Test___Invoke
{
class CLASS
{
private MAINFORM _MAINFORM = new MAINFORM();
public void _MESSENGER()
{
_MAINFORM._LOGGING("Test");
}
}
}
You are assuming that the _MAINFORM you create in the CLASS constructor is the same instance as the form where the button was clicked, which is not the case. You have a chicken-and-egg problem. Your form creates a CLASS, and the CLASS creates a form. So now you have two different forms. (or two different CLASS instances since you don't show how the first form or CLASS is created)
You need to "connect" the form and the class, either by passing the form to the constructor as a parameter or by some other means.
Finally, I would encourage you to do some research on best practices for class and member names. It's a bit disconcerting for a seasoned C# developer to see names in all caps and prefaced by underscores.
I want to get method info into attribute in C#.
something like this
Attribute
public class ReflectionAttribute : Attribute
{
public ReflectionAttribute()
{
//reflection things comes here
// for example
// var myMethod = this.GetMethodInfo()
// or something ...
}
}
Class
public class ReflectionTest
{
[Reflection()]
public string SendMessage()
{
return "Hello World";
}
}
Test Class
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
new ReflectionTest().SendMessage();
}
}
I just want to get information about SendMessage method inside attribute when SendMessage method is invoked from Form1.
is it possible? Is there any way in reflection
thank you.
It's not directly possible.
In my case, I want to get MethodInfo into attribute without reflection. However, attribute doesn't work without reflection.
You should use AoP framework (castle, unity..etc).
So here is my setup and the comment shows what I wish to do:
class Process
{
void SomeMethod()
{
// Here I want to call Parent.MethodToCall()
}
}
class Controller
{
Process c = new Process();
void MethodToCall()
{
}
}
Now the Controller.MethodToCall() will be called many times throughout the lifecycle of the Process class.
It is only the parent method that needs to be called so I believe that using an event would be a bit wasteful as I will never be removing the handler and there would only be one invocation.
So the way I am currently using to get around this is like follows:
class Process
{
public Func<void> Method { get; set; }
void SomeMethod()
{
Method();
}
}
class Controller
{
Process c = new Process() { Method = MethodToCall }
void MethodToCall()
{
}
}
First off, the syntax might not be perfect, I quickly knocked it up in notepad.
My question: What is the best way to achieve what I want because what I am doing looks quite messy to be?...or am I thinking about this completely the wrong way in terms of design?
Essentially what I want to do is call a method in the Controller class without making it public, because if it is public, I could simply pass the Controller as a parameter to the Process.
class Child
{
Parent parent=null;
public Child(Parent p)
{
parent=p;
}
void SomeMethod()
{
parent.MethodToCall();
}
}
This should be a good example of how to do that
class Child : Parent
{
private void SomeMethod()
{
base.MethodToCall();
}
}
class Parent
{
Child c = new Child();
protected void MethodToCall()
{
c.MethodToCall();//not sure if you are wanting to call c.MethodToCall();
}
}
Well, in OOP terms the correct answer would be the following:
class Child : Parent
{
void SomeMethod()
{
base.MethodToCall();
}
}
class Parent
{
protected void MethodToCall()
{
// protected methods are accesible from
// descendants and private from outside
}
}
But you can always avoid inheritance, using aggregation
What you are doing is essentially rolling your own events. Internally, event handlers are just delegates attached to the event, with the one difference that only the owner of the event can raise it.
I have been trying to work out how to call a method in a different class. Both classes are created dynamically at run-time. Most of the issues I have seen here relate to inheritance, which is different from what I have (I think.)
I am still fairly new to C#, and am trying to test some concepts out.
The first class is something like this:
public class Record
{
CustomPanel _panel;
public void recordFunc(){}
}
The internally created class has something like this:
public class CustomPanel : Panel
{
List<Control> _myControls = new List<Control>;
// _myControls[0] += new EventHandler(myFunc);
public void myFunc(object sender, EventArgs e)
{
// parentClass.recordFunc();
}
}
My objective is to create a Record at run-time from a database call. At that point, it creates a Panel (from my CustomPanel class) that gets added to a FlowLayoutControl. When events are fired from the panel's internal controls, I need to have it update parts of the parent Record class.
Any help is greatly appreciated.
I'm not 100% sure what you're asking, but it seems you want to know how to call a function on a class, when you don't know the class type at runtime, but it could be one or many record types. Is that correct?
If so, a way to cleanly achieve the above is to implement an interface on your derived types and call the interface method. For instance, if you have multiple "Record" classes and don't know the type at runtime, try the following:
public interface IRecord
{
void RecordFunc();
}
public class ARecord : IRecord
{
public void RecordFunc()
{
Console.WriteLine("ARecord.RecordFunc");
}
}
public class AnotherRecord : IRecord
{
public void RecordFunc()
{
Console.WriteLine("AnotherRecord.RecordFunc");
}
}
public class CustomPanel : Panel
{
private IRecord _parentRecord;
// Where parentRecord could be ARecord or AnotherRecord
public class CustomPanel(IRecord parentRecord)
{
_parentRecord = parentRecord;
}
public void MyFunc(object sender, EventArgs e)
{
_parentRecord.RecordFunc();
}
}
If that's not what you're looking for, please clarify.
There is no magic instance of the Record class available from within a CustomPanel just because a Record instance contains a CustomPanel. You'll have to set up such a relationship yourself. E.g.
public class Record
{
CustomPanel _panel;
public CustomPanel panel
{
get { return _panel; }
set { _panel = value; _panel.parent = this; }
}
public void recordFunc(){}
}
public class CustomPanel : Panel
{
public Record parent { get; set; }
public void myFunc(object sender, EventArgs e)
{
parent.recordFunc();
}
}
I'm trying to write my first program in C# without the use of a tutorial. To ensure that I adopt from the start good coding practices, I want to create each class in an different .cs file. However, I'm running into some troubles when trying to access the elements of the program in such an .cs file.
For example, I have an Form1.cs with an Label and a Start button. When clicking on the start button, a text should appear in the Label. So:
In Form1.cs I have:
namespace TestProgram
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void startButton_Click(object sender, EventArgs e)
{
WriteToLabel message = new WriteToLabel();
message.WelcomeMessage();
}
}
}
And in my separate WriteToLabel.cs file:
namespace TestProgram
{
public class WriteToLabel
{
public void WelcomeMessage()
{
Form1 myForm = new Form1();
//myForm.. --> myForm doesn't have an 'outputLabel'?
outputLabel.Text = "Welcome!"; // This returns an error: 'The name outputLabel does not exits in the current context'.
}
}
}
'outputLabel' is the (Name) I've given the label, and this is in accordance to the name in Form1.Designer.cs.
Both files are using the same components such as 'using System';.
However, from my WriteToLabel.cs file I can't seem to access the Form which holds my program. I did manage to succeed to create different .cs files in an Console Application, which only added to my confusion. So, I have two questions:
First, how can I access the Form from a separate class (i.e. not an partial class) in a separate file?
Second, is this the good way to do it, or is it inefficient to create multiple instances of different classes?
Any thoughts or ideas are highly welcome,
Regards,
The designer automatically creates controls as private fields, because of that your WriteToLabel class can't access it. You need to change that.
Also a good start would be to change the class to something like that:
namespace TestProgram
{
public class WriteToLabel
{
Form1 form;
public WriteToLabel(Form1 form)
{
this.form = form;
}
public void WelcomeMessage()
{
//Form1 myForm = new Form1();
//myForm.. --> myForm doesn't have an 'outputLabel'?
form.outputLabel.Text = "Welcome!";
}
}
}
You're actually instantiating a new instance of Form1, whereas you need to pass in a reference to your existing instance:
public void WelcomeMessage(Form1 form)
{
form.outputLabel.Text = "Welcome";
}
You also need to ensure that outputLabel is a public (or internal) property/field of Form1 so you can set the value accordingly. Then the calling code is slightly different:
private void startButton_Click(object sender, EventArgs e)
{
WriteToLabel message = new WriteToLabel();
message.WelcomeMessage(this);
}
You need to make sure that Form1.outputLabel has public or internal visibility.
You only need something like a LabelWriter class if the class is going to share a significant amount of state or private methods. If all you have is a bunch of methods that set properties on separate objects, you might as well just keep it as a method on the same object (in this case the Form1 object):
void startButton_Click(object sender, EventArgs e)
{
displayWelcomeMessage();
}
void displayWelcomeMessage()
{
this.outputLabel = "Welcome!";
}