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.
Related
I am having a big problem wich I cannot solve myself.
I have got two windows forms running at the same time and a separate class. To interact with the class I use this code in both forms:
private Entities entities = new Entities();
I use that in one of my forms, like so:
int hp = entities.Get_HP(CurrentEntity);
Here hp will be for example 90 or 57... But when I do the exact same thing in the other form, then it will thow an exception saying that entities.Get_HP(CurrentEntity) is null. The debugger (vs 2012) says the same.
This only happens in one form, not the other.
I really hope someone can help me with this, because I'm clueless.
Thank you, Dion Dokter.
Each time you say "new" you're getting an entirely unique instance of the object. What you want is the same instrance between the two different windows. You could use events to pass around information, or a static method somewhere, or have the windows have a custom constructor(s) with parameter(s) to share the object(s).
These are core concepts. Someone can help further if you detail your usage of your program, specifically how these forms are opened.
In Form1 change you Entities declaration to something like;
private static Entities entities = new Entities();
public static GetEntities() { return entities }
In Form2
private Entities entities;
private bool entitiesSet = false;
Where you're gonna use entities;
if (!entitiesSet)
entities = Form1.GetEntities();
Just make sure there is no code path that attempts to access methods/properties of entities before it is set in Form2 and this should do it. Not sure where this implementation stands with regard to good or bad practice as I don't work with controllers/winforms but it will definitely work.
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.
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.
I have a checkbox that I created to windows forms, how can I set it to static?
public static CheckBox checkthis;
This code creates a new one as static, what I want to do is set one that I have created in the designer to static.
Update:
I tried below answer and it worked, though the checkbox disappeared from the form and various other issues kicked in. Instead I did this create a new one and did this:
public static CheckBox checkthisnew;
...
checkthisnew = checkthis;
Either way, I have now realised that I am fail and that I just can use the state changed on the events list, so all is well...
Sorry for not making my reasoning behind this more clear, I do appreciate your answers though, thank you.
Edit the MyForm.Designer.cs file, right where the declaration for your checkbox is. Note that your changes will be reverted if you use the designer to modify the UI again so you'll have to do this again.
Nothing good can come from making a dependent UI control static. It's one thing to make a component static and that could be ok, but for something like a CheckBox, you're just asking for trouble. For starters, a single control can only have one parent. So you can't just make a single instance of your control and expect to be able to add it to multiple forms and everything will magically appear to be in sync. If you need to share some values, do it the right way and bind to them, register some events, share the value and not the control that holds the value, or other similar methods.
I also cannot recommend you modify generated files (especially if it's generated from a tool you're using all the time). If you must insist on making the control static, declare it in your source file for the class, not the designer-generated file, the classes are declared partial for a reason.
You're probably trying to share some bool value that the CheckBox represents. Make that a static property.
public partial class MyForm : Form
{
public static bool IsToggled { get; set; }
}
If somewhere down the line you want to tie that to an event or whatever, you could always change the implementation of the accessors.
Hmm... without more context, I'd suggest to use a public boolean property for this.
Having a UI item be static is not a good idea.
Try something like this:
public class MyForm : Form
{
public static bool IsWhateverSet {get; private set;}
}
How do I populate a Form from within a method in a class library? So in the example below Method1() is what's it about.
Project "UI", Windows Forms Application
reference to MyLib
public class Form1 : Form
{
...
call some methods from MyLib.MyClass
...
}
Project "MyLib", Class Library
public class MyClass
{
...
public void Method1()
{
loop through an array and ask user to validate some data on the form during each iteration
}
}
UPDATE:
To be more specific, the MyLib library contains a class that will load a .csv file into an array (which for each row will be added to a List<string[]>) and than will loop through the List<string[]> looking for "possible" duplicates. Whenever one is found the user needs to be presented (on a Form) with both records to ultimately decide if they are the same.
How do I populate a Form from within a method in a class library?
The real question is why would you want to? The library should not be responsible for something like this. This is logic specific to your workflow and UI, not something a library is typically used for. The library should provide useful data structures, but things that are specific to your application (like gathering input and deciding what to do with it) should be handled by your code.
Anyway... I feel a bit dirty saying this... you could always just pass a reference to your form type as an argument to the method (an approach that will, among other things, tightly couple the two assemblies, making one unusable without the other)...
shudder
You may use Cross/Circular-referencing but this is not advisable due to several reasons.
You may also declare a Form-type object(better if static) within the class library and pass that form as reference and you may call the child controls within that referenced variable through the member "Controls" if I'm not mistaken.
Even though Ed put that final comment in, DO NOT DO IT! Of course it's possible, but it makes no sense. Resist the temptation!
The library should implement some general functionality, i.e. provide data structures, logic methods or maybe P/Invoke methods. But in your form class is where the logical for your UI goes. Just make a method in Form1 to handle the validation. It would be a lot easier and a lot clearer.
It's a vast question.
The easiest way would be to add a reference to System.Windows.Forms in your class lib. Then, pass the window as an argument to your business class.
But although easy this solution is, it's not a clean way. In a clean layered architecture, you can't use objects of upper layers in lowers layers. It can be both a challenge to compile and a maintenance black hole. Moreover, unit testing such cases are complex.
Considering this, another solution, a bit more complex, would be to use inversion of control, using a framework like Unity, Mef or any other, or even doing it manually.
The main idea would be to create in your class library an interface that defines user interactions like this :
public interface IInputValidator {
bool IsValid(MyClass itemToValidate);
}
Then, in you windows form application, implement this interface :
public class Form1 : Form, IInputValidator {
public void CallBusinessClass() {
var myObj = new BusinessClass(this); // the key of the concept is here
myObj.Iterate();
}
public bool IsValid(MyClass itemToValidate) {
return MessageBox.Show("Is valid ?", MessageBoxButtons.YesNo) == MessageBoxButtons.Yes);
}
}
Then, in you business class :
public class BusinessClass {
private IInputValidator m_validator;
public BusinessClass(IInputValidator validator) {
this.m_validator = validator;
}
public void Iterate()
{
foreach(var item in ItemsToIterate)
{
var isValid = m_validator.IsValid(item); // call the upper layer from a lower layer
}
}
}
hope that helps