Use a method from another class ? without opening new form? - c#

Hey guys my issue is that i can't use the common class class1 = new class(); and just do class1.method1(); because if I make a new instance of the class it would open a new form and the class also has a constructor. I just need that one method from the class nothing more.

To use a class' instance method, you need an instance of that class; no exceptions*. If its constructor opens a form, make it so that it doesn't.

You may need to re-consider your design pattern as if this class1 you speak of is a Form then stopping the UI from showing in such a manner is not a particularly proper design pattern. Update your question with your current implementation so people can better advise you!
If you are manually instaniating and displaying a Form from within the class1 constructor you could consider an implementation like this:
public Class1(bool showForm)
{
if (showForm)
{
//Show UI
}
}
If you must you could hide the UI like so:
protected override void SetVisibleCore(bool value)
{
base.SetVisibleCore(false);
}

Related

Extending a class with a new nested class

first question so I'm open to advice on effectively participating in the StackOverflow community as well as pertaining to the question.
I'm working on a text-based UI in C#. I have an abstract window class and an abstract control class, each of which implements common functionality for the types that inherit them (e.g. pop-up windows or text box controls). Currently, within a program that might implement the library, a developer would have to create window objects and control objects, and then add the controls to their respective windows, and the windows to a window manager class, like this:
var mainWindow = new MainWindow(...);
var textBox1 = new TextBox(...);
mainWindow.AddControl(textBox1);
WindowManager.Add(mainWindow);
This works, but it's a bit clunky. Since a control should never have to exist outside of a window, I was hoping to implement the control types as nested types. However, to maintain extensibility of the program, I'd like for there to be a way to extend the window class with new control types. My question is this: Should I use reflection, or rely on developers using container classes to extend the window class? Alternatively, is there a better way to structure the program than how it's currently laid out?
I've also considered using generics, e.g.:
public abstract class Window : DrawableObject, IWindow
{
public void AddControl <T>(object[] constructorArgs) where T : class, IControl
{
}
}
I'm aiming for ease of implementation without sacrificing extensibility/loose coupling. Thanks in advance for any thoughts!
EDIT: Should clarify, the primary reason for this is to fix some weirdness with how Windows and Controls cooperate. Each control has a parentWindow property which is used to access the window on which a control resides, for various purposes like creating an exit button for a particular window, etc.
Right now, this property is passed to the constructor, but that seems redundant to me since after doing so you have to add the control to the window's control list. I'd like to find a way to set this property when the control is added to a window instead, but restrict this action to when the control is added only, to prevent potential problems if the parentWindow property is changed outside of this context.
The way you coded AddControl method:
public void AddControl <T>(object[] constructorArgs)
where T : class, IControl
{
}
You intend developers to just provide type and your AddControl method will create an instance of it using constructorArgs. This method itself implicitly forces you to use reflection. Anything else does not stand a chance. Because To Add control of type T, Creating Instance of Control of type T is necessary. Since your Window class does not have a clue about T reflection is the only solution.
To facilitate other approaches, you might want to consider few overloads of AddControl.
public virtual T AddControl <T>()
where T : class, new(),IControl
{
//now you can create instance no reflection required
var control = new T();
this.Controls.Add(control);
return control;
}
public void AddControl <T>(T control)
where T : class, IControl
{
}
public abstract void AddControl <T>(object[] constructorArgs)
where T : class, IControl;
Creating an abstract method passes onus of implementation on child class and creating new instance of T can be handled the assuming type of T is known there or at-least all cases of known types of what T might be are handled.
It's a wide scope topic and I guess subjective as well. The best use of OOP is to achieve a design which fits your logical objective whatever that maybe.

Is it a bad idea to give a C# form a static property pointing to the only instance of the same form?

I have a fairly simple application that monitors folder activity and logs it on a server.
In this application I start off with a Form object called Form1. On this form I have a NotifyIcon. Because I need to change the text in the BalloonTip of the NotifyIcon from different Forms along the way, I was thinking of setting a static property of Form1 that will point to the only instance of Form1. This is how it would look in my oppinion:
public partial class Form1 : Form
{
private static Form1 staticRef;
// Other private properties
public Form1()
{
InitializeComponent();
staticRef = this;
// Rest of constructor logic
}
public static void changeNotifyBalloonText(String newText, int timeInMillis)
{
if (staticRef != null && staticRef.notifyIcon1 != null)
{
staticRef.notifyIcon1.BalloonTipText = newText;
staticRef.notifyIcon1.ShowBalloonTip(timeInMillis);
}
}
// Rest of public and private methods
}
Other things to be noted:
a. There will never be more than 1 instance of Form1.
b. I always check the value of staticRef against null, before trying to use it.
c. I cannot afford to make a temporary, local instance of Form1 just to set a BalloonTip message.
d. This solution works very well, i'm more interested in knowing if it's "too hacky" and if so - what would be a better approach to my issue?
e. The closest thing I've found that may answer my question (about static properties) to some degree is here:
Is using a static property in a form bad practice knowing that there's only only one instance of the form?
What you have here is a form of the singleton pattern.
The singleton pattern certainly has its detractors and its defenders (google "singleton anti-pattern").
It is though a very convenient way of doing this.
I would recommend an approach like either::
Create a class that represents operations on a notify icon.
Have that class as the only class that accesses staticRef.notifyIcon1.
Have it do so as a reference to notifyIcon1, not as Form1.
Have a static method or property that gets the icon-controlling class.
Or:
Simply have a static method or property that returns the NotifyIcon object.
Make it the only method that accesses the static reference to the form.
The advantage of one over the other is around whether you want to expose the full interface of NotifyIcon or provide a set of operations that make sense to your application.
This way you are still using the singleton pattern, but in restricting the way that it is accessed the fact that there is global state has less of a global impact, relates more directly to the purpose of that global state (the icon itself), and is more readily extended to different uses. e.g. if you some day need to have two icons, you change the method that static method or property to one that does a lookup of some sort, and change all the current calls to use the key for the first icon. Meanwhile, implementation changes up to and including completely changing which form provides that icon can be done quickly in one place.
I think your current design is tightly coupled to other classes sending the notification and it requires your form to be a single instance as well.
You can decouple this a great deal by using an event broker to send the notification to any interested parties. Many frameworks have event brokers, I have used one from Prism but there are others as well.
Your code will then only know about the event broker and what events your class is interested in.
public partial class Form1 : Form
{
private static IEventBroker eventBroker;
// Other private properties
public Form1(IEventBroker eventBroker)
{
InitializeComponent();
this.eventBroker = eventBroker;
this.eventBroker.Register<NotifyBaloonText>(changeNotifyBalloonText);
}
public static void changeNotifyBalloonText(NotifyBaloonText args)
{
notifyIcon1.BalloonTipText = args.NewText;
notifyIcon1.ShowBalloonTip(args.TimeInMillis);
}
// Rest of public and private methods
}

C# Winforms Designer calling base property instead of 'new' one?

I have a class that inherits from another class, who has a non-virtual property ("Controls").
Since I can't overwrite this property, Im using the 'new' keyword associated with my property.
At runtime, this property is called as I want it to, in the correct context.
When I open my form from the designer, the designer calls the base.Controls instead of my 'new' control.
Am I missing something, or is this just incorrect behavior in the winforms designer?
Edit, added the code in question for more explanation. I have the following class:
public partial class BauerGroupBox : ComponentFactory.Krypton.Toolkit.KryptonGroupBox
{
public BauerGroupBox()
: base()
{
}
public new Control.ControlCollection Controls
{
get
{
MessageBox.Show("GOT THERE");
return this.Panel.Controls;
}
}
}
When I get to the following code in my intializecomponent:
BauerGroupBox thisBox = new BauerGroupBox()
thisBox.Controls.Add(something)
When I add a new 'BauerGroupBox' to my code, it works fine. However, when I open my code in the designer (even while using the debugging the devenv), the messagebox is NOT shown, and the breakpoint is NOT hit.
When I run my app, the breakpoint is hit.
You're missing something - what you're describing is correct behaviour.
The workaround is to re-populate your new Controls property right after the call to InitializeComponent(). Like so:
public MyForm() {
InitializeComponent();
this.Controls.AddRange( base.Controls );
}
However, why are you trying to "override" the Controls property? What new, non-standard, behaviour are you after? I believe there is a better alternative.
You misunderstand how the new keyword works. New doesn't override the property, it hides it. If you reference the object as it's base element, it will still call the base property, not your new one. The only way to use the new one is to reference it as the new one. ie.
public class A {
public A1 {get;set;}
}
public class B : A {
public new A1 {get;set;}
}
B b = new B();
A a = b;
a.A1; // references A.A1
b.A1; // references B.A1
I think I understand your situation, so let me explain what the designer is doing:
First, at runtime, you are effectively running an instance of your BauerGroupBox control. (That said, it's also all likely that you are accessing the Controls property through a reference of this derived type, namely BauerGroupBox, and as #Mystere Man correctly argues, the member BauerGroupBox.Controls hides the inherited member (wherever it is last defined) -- it does not override it.
Bur the issue in question is that at design-time, in the designer of the BauerGroupBox control, you are NOT "running" an instance of BauerGroupBox, instead you are designing a prototype based on ComponentFactory.Krypton.Toolkit.KryptonGroupBox and that is effectively the type of the control you are "running".
I repeat, the designer of BauerGroupBox does not have an instance of BauerGroupBox running, but an instance of ComponentFactory.Krypton.Toolkit.KryptonGroupBox. No BauerGroupBox exists in the designer, because, well.. you are designing it!!!
NOW, to add a bit more confusion to that (none really, it's all very simple if you think a bit about it,) you will see that if you go to any other designer of any other control, say a form, and then you drag and drop an instance of your BauerGroupBox, and add some controls to it, you will your message box, and yes, in that case, just like in the "runtime" case, it means that you are effectively hosting a BauerGroupBox... but in this case, you are not designing BauerGroupBox.
As other #Dai mentioned, if what you're trying to do is to prevent people from adding controls to it, then you should follow other design plans: for example, override the
protected virtual Control.ControlCollection CreateControlsInstance();
method.

Trying to figure how to call function from other class without making it static

I'm trying to change a listbox in my main form from another file (nodes.cs) which contains another class. I created a class in my main form that changes the textbox for me so all I need to do it pass the string to it. Unfortunately, I can't access the function from the other class unless I make the String-changing-class static. If I make it static, I can't change the listbox without getting an error:
An object reference is required for the non-static field, method, or property...
I know this means I need to create the object or make it non-static. I find the whole class thing rather confusing. I have to initiate a whole new form object to access it? Anyways.
How do I go about accessing a Listbox from another Class, contained in another file? The two classes are in the same namespace.
there's no real point in adding what I have, it's a huge amount of code, and i erased everything I've tried already...
MAIN.CS
namespace neuralnetwork
{
public partial class mainform : Form
{
yada yada
public static void changetext(string text)
{
listbox1.items.add(text);
}
}
}
Secondary.cs
namespace neuralnetwork
{
class lolercopter
{
public static void dolol()
{
//here is where I want to change the mainforms textbox.
mainform.changetext(s);
}
}
}
This is essentially what I have. I've been reading for over an hour on this...
You can pass a reference to mainform into your method:
public static void dolol(mainform frm)
{
frm.changetext(s);
}
Your question leads me to suspect that you have some serious architecture issues with this application, but hopefully this solution can work for you.
classes are like blueprints.
What you're asking is like asking how to open the door down the hall on the blueprint.
It sounds like you want action on one form to trigger action or changed state on another form. That could be achieved by storing state in a database, or in memory, but ideally by having a reference to the instantiated mainform.
How is your nodes class created? Is it created by the form? If so, you could pass in a reference to the form when you create the nodes class.
For example, say you have this code in a callback in the form.
var nodes = new Nodes();
nodes.UpdateSomething( args );
You could change the constructor for the Nodes class so that it takes a reference to form. This is called Dependency Injection, specifically constructor injection. Your class has a dependency on the form, you provide the form when you create the class.
var nodes = new Nodes( this ); // "this" is a reference to the form
nodes.UpdateSomething( args );
Your Nodes class would then use the helper as:
public class Nodes
{
private Form TheForm { get; set; }
public Nodes( Form form )
{
this.TheForm = form;
}
public void UpdateSomething( EventArgs args )
{
...
this.Form.ChangeText( newValue );
...
}
}
The basic idea is to provide the class the resources that it needs access to via the constructor so you don't have to make use of long-lived object references and static classes.
EDIT: I've updated this to reflect your code sample. Note that you're not providing a new class in the form to change the list box, but rather a method.

'UserControl' constructor with parameters in C#

Call me crazy, but I'm the type of guy that likes constructors with parameters (if needed), as opposed to a constructor with no parameters followed by setting properties. My thought process: if the properties are required to actually construct the object, they should go in the constructor. I get two advantages:
I know that when an object is constructed (without error/exception), my object is good.
It helps avoid forgetting to set a certain property.
This mindset is starting to hurt me in regards to form/usercontrol development. Imagine this UserControl:
public partial class MyUserControl : UserControl
{
public MyUserControl(int parm1, string parm2)
{
// We'll do something with the parms, I promise
InitializeComponent();
}
}
At designtime, if I drop this UserControl on a form, I get an Exception:
Failed to create component 'MyUserControl' ...
System.MissingMethodException - No parameterless constructor defined for this object.
It seems like, to me, the only way around that was to add the default constructor (unless someone else knows a way).
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}
public MyUserControl(int parm1, string parm2)
{
// We'll do something with the parms, I promise
InitializeComponent();
}
}
The whole point of not including the parameterless constructor was to avoid using it. And I can't even use the DesignMode property to do something like:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
if (this.DesignMode)
{
InitializeComponent();
return;
}
throw new Exception("Use constructor with parameters");
}
}
This doesn't work either:
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
Fine, moving along ...
I have my parameterless constructor, I can drop it on the form, and the form's InitializeComponent will look like this:
private void InitializeComponent()
{
this.myControl1 = new MyControl();
// blah, blah
}
And trust me, because I did it (yes, ignoring the comments Visual Studio generated), I tried messing around and I passed parameters to InitializeComponent so that I could pass them to the constructor of MyControl.
Which leads me to this:
public MyForm()
{
InitializeComponent(); // Constructed once with no parameters
// Constructed a second time, what I really want
this.myControl1 = new MyControl(anInt, aString);
}
For me to use a UserControl with parameters to the constructor, I have to add a second constructor that I don't need? And instantiate the control twice?
I feel like I must be doing something wrong. Thoughts? Opinions? Assurance (hopefully)?
Design decisions made regarding the way Windows Forms works more or less preclude parameterized .ctors for windows forms components. You can use them, but when you do you're stepping outside the generally approved mechanisms. Rather, Windows Forms prefers initialization of values via properties. This is a valid design technique, if not widely used.
This has some benefits, though.
Ease of use for clients. Client code doesn't need to track down a bunch of data, it can immediately create something and just see it with sensible (if uninteresting) results.
Ease of use for the designer. Designer code is clearer and easier to parse in general.
Discourages unusual data dependencies within a single component. (Though even microsoft blew this one with the SplitContainer)
There's a lot of support in forms for working properly with the designer in this technique also. Things like DefaultValueAttribute, DesignerSerializationVisibilityAttribute, and BrowsableAttribute give you the opportunity to provide a rich client experience with minimal effort.
(This isn't the only compromise that was made for client experience in windows forms. Abstract base class components can get hairy too.)
I'd suggest sticking with a parameterless constructor and working within the windows forms design principles. If there are real preconditions that your UserControl must enforce, encapsulate them in another class and then assign an instance of that class to your control via a property. This will give a bit better separation of concern as well.
There are two competing paradigms for designing classes:
Use parameterless constructors and set a bunch of properties afterwards
Use parameterized constructors to set properties in the constructor
The Visual Studio Windows Forms Designer forces you to provide a parameterless constuctor on controls in order to work properly. Actually, it only requires a parameterless constructor in order to instantiate controls, but not to design them (the designer will actually parse the InitializeComponent method while designing a control). This means that you can use the designer to design a form or user control without a parameterless constructor, but you cannot design another control to use that control because the designer will fail to instantiate it.
If you don't intend to programmatically instantiate your controls (i.e. build your UI "by hand"), then don't worry about creating parameterized constructors, since they won't be used. Even if you are going to programmatically instantiate your controls, you may want to provide a parameterless constructor so they can still be used in the designer if need be.
Regardless of which paradigm you use, it is also generally a good idea to put lengthy initialization code in the OnLoad() method, especially since the DesignMode property will work at load time, but not work in the constructor.
I would recommend
public partial class MyUserControl : UserControl
{
private int _parm1;
private string _parm2;
private MyUserControl()
{
InitializeComponent();
}
public MyUserControl(int parm1, string parm2) : this()
{
_parm1 = parm1;
_parm2 = parm2;
}
}
As this way the base constructor is always called first and any references to components are valid.
You could then overload the public ctor if need be, ensuring the control is always instantiated with the correct values.
Either way, you ensure that the parameterless ctor is never called.
I haven't tested this so if it falls over I apologise!
This is unfortunately a design issue that will occur frequently, not just in the control space.
There are often situations where you need to have a parameterless constructor, even though a parameterless constructor is not ideal. For example, many value types, IMO, would be better off without parameterless constructors, but it's impossible to create one that works that way.
In these situations, you have to just design the control/component in the best manner possible. Using reasonable (and preferably the most common) default parameters can help dramatically, since you can at least (hopefully) initialize the component with a good value.
Also, try to design the component in a way that you can change these properties after the component is generated. With Windows Forms components, this is typically fine, since you can pretty much do anything until load time safely.
Again, I agree - this isn't ideal, but it's just something we have to live with and work around.
Well, in short, the designer is the kind of guy that likes parameter-less constructors. So, to the best of my knowledge, if you really want to use parameter based constructors you are probably stuck with working around it one way or the other.
Just do this:
public partial class MyUserControl : UserControl
{
public MyUserControl() : this(-1, string.Empty)
{
}
public MyUserControl(int parm1, string parm2)
{
// We'll do something with the parms, I promise
if (parm1 == -1) { ... }
InitializeComponent();
}
}
Then the 'real' constructor can act accordingly.
Provide a parameterless constructor for the designer and make it private - if you really must do it this way... :-)
EDIT: Well of course this won't work for UserControls. I obviously wasn't thinking clearly. The designer need to execute the code in InitializeComponent() and it's can't work if the constructor is private. Sorry about that. It does work for forms, however.
It's quite a while since the question was asked, but maybe my approach is helpful to somebody.
I personally also prefer to use parameterized Constructors to avoid forgetting to set a certain property.
So instead of using the actual Constructor I simply define a public void PostConstructor where all things are put you would normally put in the Constructor. So the Actual Constructor of the UserControl always contains only InitializeComponent().
This way you don't have to adjust your favourite programming paradigm to VisualStudios needs to run the Designer properly. For this programming schema to work it has to be followed from the very bottom.
In practice this PostConstructionalizm would look somewhat like this:
Let's start with a Control at the bottom of your UserControl call hierarchy.
public partial class ChildControl : UserControl
{
public ChildControl()
{
InitializeComponent();
}
public void PostConstructor(YourParameters[])
{
//setting parameters/fillingdata into form
}
}
So a UserControl containing the ChildControl would look something like that:
public partial class FatherControl : UserControl
{
public FatherControl()
{
InitializeComponent();
}
public void PostConstructor(YourParameters[])
{
ChildControl.PostConstructor(YourParameters[])
//setting parameters/fillingdata into form
}
}
And finally a Form calling one of the User Control simply puts the PostConstructor after InitializeComponent.
public partial class UI : Form
{
public UI(yourParameters[])
{
InitializeComponent();
FatherControl.PostConstructor(yourParameters[]);
}
}
I have a way to work around it.
Create a control A on the form with the parameterless constructor.
Create a control B with parameterized constructor in the form contstructor.
Copy position and size from A to B.
Make A invisible.
Add B to A's parent.
Hope this will help. I just encountered the same question and tried and tested this method.
Code for demonstrate:
public Form1()
{
InitializeComponent();
var holder = PositionHolderAlgorithmComboBox;
holder.Visible = false;
fixedKAlgorithmComboBox = new MiCluster.UI.Controls.AlgorithmComboBox(c => c.CanFixK);
fixedKAlgorithmComboBox.Name = "fixedKAlgorithmComboBox";
fixedKAlgorithmComboBox.Location = holder.Location;
fixedKAlgorithmComboBox.Size = new System.Drawing.Size(holder.Width, holder.Height);
holder.Parent.Controls.Add(fixedKAlgorithmComboBox);
}
holder is Control A, fixedKAlgorithmComboBox is Control B.
An even better and complete solution would be to use reflect to copy the properties one by one from A to B. For the time being, I am busy and I am not doing this. Maybe in the future I will come back with the code. But it is not that hard and I believe you can do it yourself.
I had a similar problem trying to pass an object created in the main Windows Form to a custom UserControl form. What worked for me was adding a property with a default value to the UserControl.Designer.cs and updating it after the InitializeComponent() call in the main form. Having a default value prevents WinForms designer from throwing an "Object reference not set to an instance of an object" error.
Example:
// MainForm.cs
public partial class MainForm : Form
public MainForm()
{
/* code for parsing configuration parameters which producs in <myObj> myConfig */
InitializeComponent();
myUserControl1.config = myConfig; // set the config property to myConfig object
}
//myUserControl.Designer.cs
partial class myUserControl
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
// define the public property to hold the config and give it a default value
private myObj _config = new myObj(param1, param2, ...);
public myObj config
{
get
{
return _config ;
}
set
{
_config = value;
}
}
#region Component Designer generated code
...
}
Hope this helps!

Categories