Instantiating each of the two classes in one another - c#

I have a C# class question which I hope to get some help with. I have one class called CountdownUserControl. There are a number of functions within this class. I then have another class called Min. There are certain things I need in this form within CountdownUserControl class so I create an instance of it within CountdownUserControl:
public partial class CountdownUserControl : UserControl
{
//-----------------------------------------------
// Private data members
//-----------------------------------------------
private Min _Min = new Min();
However within the Min class I also would like to use a function which is contained within the CountdownUserControl class - however I cannot create an instance of it within the Min class such as
public partial class Min : Form
{
private CountdownUserControl CU = new CountdownUserControl();
so that within Min class I could do CU.Method_I_want();
as this will give a stackoverflow. Does anyone know a solution around this? Thanks for your time.

Classes and methods
Classes shouldn't just been seen as a collection of methods, when they are created ('instantiated') with new, they become actual objects that should be treated as such.
You need to re-think your strategy and instead simply reference a Min or CoundownUserControl object. What does each one represent? You are suggesting that the UserControl (a part of a Form) needs to have its own Form created for it - that's not the case. The Form is the object that creates the UserControl. The UserControl can access the Form by using the ParentForm property.
The StackOverflow
When you do this: new Min() you are creating a new Min object. Then, in Min, when you do this: new CountdownUserControl() you are creating a new CoundownUserControl object. Which in turn creates a new Min object, and so on and so forth.
How to fix your problem
Simply put, use Min min = (Min)this.ParentForm; within the user control if you are sure the user control is on a Form whose type is Min.
And finally/additionally, you should not create the instance of CountdownUserControl yourself unless you are going to set the properties and add it to the Controls collection of the form within your code. Instead, build your project, drag-and-drop the CountdownUserControl onto your form - a property to access the control will be created on your Min class automatically, called countdownUserControl1.

All these answers are great, but you should also consider the fact that cyclic dependencies are generally really difficult to work with. Your classes should be somewhat isolated units with a single purpose. They should be loosely coupled from each other. If you redesign your classes to eliminate cyclic dependencies and follow these guidelines, you will write better and more maintainable code in general and will have less issues like this in the first place.

There surely are plenty of solutions to this. An easy one would be to pass the current Min to CountdownUserControl in its constructor (or vice versa):
private Min min;
public CountdownUserControl(Min min)
{
this.min = min;
}
When you are facing these kind of problems, there probably is something wrong with your class structure, though. Maybe you could split some of the functionality out of your classes into a new one to avoid this problem.

Instead of instantiating a new Min class every time, you could set the value of it in a constructor.
public CountdownUserControl(Min min)
{
_Min = min;
...

Is CountdownUserControl going to be on the Form Min? Why would you instantiate the form from the control, and not the reverse? Shouldn't the Countdown control be on the form? Then you could instantiate the form, initialize the control, and then access the function.

The problem here is that whenever a CountdownUserControl is created, it tries to create a new Min, but whenever a new Min is created, it tries to create a new CountdownUserControl. This process could continue indefinitely and therefore the stack is blown.
The solution is to inject the instance of CountdownUserControl into Min (Or vice versa, depending on what gets created first).
So CountdownUserControl will look like this:
public partial class CountdownUserControl : UserControl
{
//-----------------------------------------------
// Private data members
//-----------------------------------------------
private Min _Min;
public CountdownUserControl(Min min)
{
_Min = min;
}
...and Min will look like this:
public partial class Min : Form
{
private CountdownUserControl CU;
public Min()
{
CU = new CountdownUserControl(this);
}

Do not create a form in the user control. Add it as a dependency:
public partial class CountdownUserControl : UserControl
{
private Min _Min;
public CountdownUserControl(Min parentForm);
And then use it in your form:
public partial class Min : Form
{
private CountdownUserControl CU;
public Min()
{
CU = new CountdownUserControl (this);
}
Update
A more suitable solution would be to break out the common functionality from the two classes and put them in separate classes. Read up on single responsibility principle. I got a post about it in my blog.

You can pass in an instance of your CountdownUserControl to your Min class (via an additional constructor parameter or via a property).
public partial class Min: Form {
public Min() {
InitializeComponent();
}
public CountdownUserControl Countdown {get;set;}
}
Since this is a form you probably want to go with the property so as not to break the designer.
I won't speak to whether or not this is proper form (hopefullt you are using something like PresentationModel or MVC), as I do know tehre are times code like this is required.
Now as has been pointed out, if you plan on showing the user control in the form then a different solution should be adopted. But it all depends on how you are planning on what you are doing with the form. If you are for example showing teh form in a dialog keeping a class level reference is a bad idea since once closed the form will be disposed.
A little more detail would get you closer to a fully correct answer.

However within the Min class I also would like to use a function which is contained within the CountdownUserControl class - however I cannot create an instance of it within the Min class such as
Is it really necessary that mentioned function is member of CountdownUserControl?
Could you reveal more of public interface of your classes?
If the function has no reference to instance of CountdownUserControl consider changing it to static. Else try to design new class named e.g. CountdownState whose instance may be shared among both CountdownUserControl and Min.

Related

Using ref in (whole) partial class

I got some confusion about "the right way" to use a reference in a partial class.
Basically i wrote a WPF program which has different Menus. Every Menu got the same Viewmodel and some data-related object class. In my case i call the Object "DataModel" which i want to use as reference in every menu. I just came across a problem when ich switched my DataModel from a static object to the desired instance for every Menu as input ref. (i still want to use one and the same DataModel for every menu though...)
But in the "lower" methods it says that _dm is simply not defined.
Code shortly summarized as:
public partial class FormatWPF : UserControl
{
public FormatWPF(DataModel _dm)
{
InitializeComponent();
if (this.DataContext == null)
{
this.DataContext = _dm.g1.MVM;
}
}
// here come several Methods with which i want to calculate stuff and "manipulate" the DataModel
private void Steinformat_berechnen()
{
_dm.g1.FormatNr = _dm.g1.FormatAnzahl + 1;
}
//....
}
Shortly said i want to use the _dm which is given as input ref in the Constructor of the class object for every other method in the whole partial class as well (is it really necessary to define this ref for every method ?) Using the DataModel as static seemed so easy for me.... but basically it is "wrong" ?
Thanks in advance for some help and tips about doing it the right way.
Maybe i was a little bit unclear. The thing is i want to use just one DataModel for all the menu and my whole project. Nevertheless i dont want to make it as static ( there occured some other confusion in later parts of my code... ) So basically i have to give in the DataModel as ref for all the Menus...
Concerning your answer: I know the possibility to define another
private Datamodel _dm;
in the namespace..
But im not quite sure about:
1)won't i got here some additional "memory" usage by defining another DataModel for every menu ? becuase it is somehow "big"
2)when i now calculate data in the _dm, will it change for the "complete" program ? like in the former static Model ?
I hope to make the DataModel static then is not the "right answer" to my problem because i just wanted to get away from this somehow ... hm
Best regards
Knally
Yes, static is very wrong if the DataModel is a per-instance thing (static means all the instances would be using the same value); but it can still be an instance field:
private DataModel _dm;
public FormatWPF(DataModel dataModel)
{
_dm = dataModel;
// the rest of your constructor code here
}
Now you can use _dm in all of your other instance methods, and everything should be fine. If you only ever need _dm.g1, you could perhaps store that value as the field, instead of the model itself.

Execute a method from all instances of a class

I am designing a base class for TextForms and derived classes for Labels , Fields, Dialogboxes... etc.
i am using the below code
public class TextForm
{
public void Refresh()
{
}
}
public class Label : TextForms
{
public void Refresh()
{
}
}
and in my program i am instanciating many Labels .. and somewhere i need to call TextForms.Refresh() which must execute all derived classes instances Refresh() method .
i can't imagine how to do?
You can't find all the instances by default. Though, there are a few design patterns that will make it easier for you to do so. There is the Composite Design Pattern Which gives you the ability to add sub components to your components. For example, a Form/Window component will be a container of sub components like Labels and TextFields for example. Then, when you will call Refresh on the container (Form/Window - for example) it can call the Refresh on all of it's sub components.
There is also the Observable Design Pattern which let components register for 'events' (not necessarily implemented via .Net's Events). Then when you call the Refresh method on the observer, it will call the Refresh methods of all the observable's that are registered.
In your question, you write TextForms so I am assuming that this is an object that is an enumerable of some sort.
Liskows substitution principle dictates that if you have a base class of any kind you can always substitute derived classes for the base class
var textForms = new List<TextForm>();
textForms.Add(new Label());
textForms.Add(new TextBox());
so now you can simply iterate through this list as such:
foreach(var textForm in textForms){
((TextForm) textForm).Refresh();
}
You may have to tweak the example a little to get it working, but that is the general answer to your question.
Like m102 said it is unpractical if not impossible to find all instances. However, assuming you use a canvas or page to display your labels on, it is possible to get all the labels in that canvas.
TextForm tf = new TextForm();
foreach (Control ctrl in yourCanvas.Children.OfType<Label>())
{
tf.Refresh();
}
This will retrieve all the controls of type label from the canvas. This will not refresh them all at once.
Note: I do not recommend changing labels that are not visible/onscreen. It would require them to be kept in memory and this is performancewise not advised. Oh and your refresh function has a capital R (This is usually reserved for classes).

How to fix "inaccessible due to its protection level" error in winform?

I have a Form class
partial class ProgressMainForm : Form
{
public ProgressMainForm()
{
InitializeComponent();
}
}
And then a class that uses that class and contains all functionality for the user
public class ProgressForm
{
public ProgressMainForm myProgressForm;
public ProgressForm(string title)
{
myProgressForm = new ProgressMainForm();
myProgressForm.Text = title;
}
public void SetProgressBar(int min, int max)
{
....
}
I then use this ProgressForm class in my project like this
progresswindow = new ProgressForm("Replacing All Strings");
This way progresswindow only contains members that are related to the functionality of the ProgressForm and all those Form members are hidden from the user.
But sometimes I need to access those Form members, for example when I need Invoke method.
Is there a way to make myProgressForm in ProgressForm accessible to users without making ProgressMainForm public?
Or is this approach wrong?
In my opinion you should not work with the form directly. If I read your setup correctly, you want to show progress indicator while some job is being done. ProgressForm should expose methods to set the counters and increment them; as you run it on another thread, form manipulation should be done from inside the methods of ProgressForm. Your Invokes belong there, wrapped in suitable methods. If you want to change some visual properties of ProgressMainForm relay those properties to ProgressForm.
To resume, calling code should have no clue what ProgressForm does other than setting progress boundaries, starting, setting current percentage and stopping. This way, if you are asked to port the application to another UI system the amount of code you will need to change will be drastically reduced.
Is there a way to make myProgressForm in ProgressForm accessible to users without making ProgressMainForm public?
Yes, you can create some public properties on ProgressForm that expose specific properties of ProgressMainForm.
private ProgressMainForm myProgressForm;
public int SomeProperty
{
get { return myProgressForm.IntProp; }
set { myProgressForm.IntProp = value; }
}
For readonly properties, omit the set, and for any types that are reference types, you may want to return a clone or copy (to ensure the client can't change it).
Wrap or Expose the Methods you need. But somehow i don't like the approach, restricting the access is not a bad idea but should not be the whole purpose of this kind of abstraction. Try to make the acess easier, not restrictive.
You can declare the methods as internal , This will allow you to call the methods from within the assembly.

Changing a form object's property from a separate class

I'm very new to using C#. If you have ever heard of the Karol the robot program that is written in Java then that's what I'm aiming to build.
But I am stumbling at almost the first hurdle, I want to make a class for Karol (It is just a picture) that can move around the screen in blocks of 32x32 squares.
Trouble is when you create a class you can't access the properties of form objects because they are separate things.
I would like to be able to manipulate form objects from my class but without having to pass the object through the method each time I use it.
Any help is much appreciated.
Do not need to pass a reference of the Form every time. Should be enough to do something like this:
`public class Karol
{
private Form _form=null;
public Karol(Form frm) {
_form = frm;
}
// after use _form inside the functions and properties of the class, where needed
}`
edit
to acces a control data inside a Form it needs to expose or controls itself, like
public Label MyFormLabel {....}
Or expose a functions/properties that sets or gets the data from the control.
public string MyFormLabelText { get{ return label.Text;} set{label.Text = value;}}
If it's just one form object that "Karol" is manipulating, you should be able to pass it to the constructor and save it for use in later member calls. That way you only pass it once at construction time.

Accessing derived class from base class object issue

I have a kind of weird situation ...
I have a User Control in WPF witch in turn has some other User Controls attached to it, then I have a huge C# code file with a big algorithm which needs access to the User Control UI Elements and methods, this hole process works with a Timer which sends data to the C# code file algorithm from the User Control and it needs to return and update the UI elements from the control and also to access it's methods...
Now the thing is I don't want to put this huge algorithm in the codebehind file of my control, instead I would like to access the control's UI elements and declared methods from that code file ...
What I tried so far is to actually derive the code file's class from the User Control I use, this works fine and dandy but to access the derived class I need to create a new object of it and the UI that I get shown does not get updated since it also creates a new base class object I believe ...
so I have something like:
public partial class usrctrlSimulator : UserControl
{
public usrctrlSimulator()
{
this.InitializeComponent();
}
public void StartSimulator()
{
Algorithm = new csAlgorithm();
Algorithm.InitializeSimulator();
timer1.Start();
}
}
public class csAlgorithm : usrctrlSimulator
{
public csAlgorithm()
{
}
public void InitializeSimulator()
{
txtblkSimulatorStatus.Text = "Started"; // this element would be from the user control
}
}
So my question is : how do I call the derived class without instantiating a new object of it, since that will cause a new user control object to be created and the displayed UI will not be updated ... or if I don't derive the Algorithm class, what possibility do I have to access the user control elements and methods ?
If you want to stick with one instance of the control and still have access to the functionality in the derived class then you need to use the derived class as the control. So instead of an instance of usrctrlSimulator, you'd use csAlgorithm everywhere.
However, I'm not sure whether this design is the best approach in your scenario. The algorithm is not really a user control so maybe deriving from usrctrlSimulator is not the ideal option. For example: UserControl has a method called ApplyTemplate(). What would be the meaning of this in csAlgorithm? You can also look at it from a different angle: Would it be reasonable to use csAlgorithm wherever you could use UserControl, e.g. when invoking UserControl.AddLogicalChild(csAlgorithm)?
A different option would be to instantiate the algorithm as a member variable in usrctrlSimulator (composite). In that case you could still use it inside the usrctrlSimulator but you would have a clear separation of two concepts: A UserControl on one hand, and the implementation of an algorithm on the other hand. In addition you could then change either one of them with only limited impact on the other.
In that case your code would look as follows:
public partial class usrctrlSimulator : UserControl
{
public usrctrlSimulator()
{
this.InitializeComponent();
}
public void StartSimulator()
{
_algorithm= new csAlgorithm();
_algorithm.InitializeSimulator();
timer1.Start();
}
private csAlgorithm _algorithm;
}
public class csAlgorithm // not a UserControl anymore
{
public csAlgorithm()
{
}
public void InitializeSimulator()
{
txtblkSimulatorStatus.Text = "Started"; // this element would be from the user control
}
}

Categories

Resources