Creating a method for an operation in a separate class file - c#

I'm trying to call a method from a different class but with no succes.
I have a CheckBox checkBox1 in my program, and I have a button that when I click it I want to uncheck the checkBox1.
If I put I method in the same file like this everything works:
public void close()
{
checkBox1.IsChecked=false;
}
But if I create a separate class file (class Close), and put there (in the same namespace, and with "using" the required elements). There no way to make it work. I tried to instance the class as:
Close operation = new Close();
operation.close();
I also tried to put the close method as static, but I was impossible because in my real program I have lots of variables that gives me an error because they are "non static" (?).
I've noticed that a MessageBox.Show("Hello"); works if I call the method this way, but the checkBox1 still unchanged. What can I do?

A basic principle of Object Oriented Programming is Encapsulation. It means that a class knows and operates only on the internal member variables of the class.
In your case the class Close doesn't know anything of the control variable named checkBox1 and thus, the method close (as written above) cannot operate. It could not even be compiled!. Instead, when the method close is part of the Window class it works as expected because the control variable checkbox1 is a member variable of the window class
However, if I understand your intentions, I advise you to avoid to create separate classes to handle user interface operations. Let the code that works with the UI elements stay with the class where the elements are defined.

The CheckBox.IsChecked returns a value of type bool, if you are trying to actually change the value of the check box (i.e. checked or not-checked) you need to use a different property.
Try:
public void close()
{
checkBox1.Checked = true;
}
This is assuming that the Close class indeed has a CheckBox control inside of it... your question is rather vague, and frankly naming a method close is probably not the best practice as .Close() is a fairly common method on many classes in WinForms.

Related

C# How can I pass a UI control reference to a class module "generically" and access it' s properties?

I have done a fair amount of C# programming, but it's been all very small stuff, and coming from a C background (not C++) in the embedded space I haven't fully embraced the OO approach, and I'm happy to say I'm trying to change that.
I'm rewriting some serial comm code I've used over and over into a Class Module that I can just drop into future projects and instantiate. I have everything working except one thing: a logging function where I write the com characters to a textbox and the indices from a ring buffer into labels. I can make that all work, actually, but I was hoping to "generalize" more and pass one of any number of things with a ".Text" property for the ring buffer indices (for example, a Label, a TextBox, or a ToolStripStatusLabel).
Here’s the example, say I have a form with a text box, a label, and a ToolStripStatusLabel. The GUI is on one thread and my class module is running on another one (mostly because it is dealing with the serial port, which is perhaps inconsequential to the question?)
Anyway, lets say I have a modular variable in my class (declared as “Object”?) and I want to create a method in the object to pass in a refence to any one of those three UI elements, each one of which has the “.Text” property to which I can write.
The Class module has a delegate to invoke that will allow it to write to another gui element on the form called txtLog which is visually logging the data. At the same time I want to write something to this other passed-in UI object (say I want to display the index variable from the ring buffer).
It works fine if I stick to a Label (or any one of them) and declare everything as a Label:
===================
Up at the top, the modular variable to hold the control reference:
System.Windows.Forms.Label inPtrLbl;
And then a method to pass the assignment into the class:
public void TurnOnLogging(System.Windows.Forms.TextBox location, System.Windows.Forms.Label inLbl, System.Windows.Forms.Label outLbl)
{
comLogging = true;
logBox = location;
inPtrLbl= new System.Windows.Forms.Label();
inPtrLbl = inLbl;
}
Because the class and the form are on different threads, you need to use the Invoke stuff:
private delegate void UpdateUiTextDelegate(byte text, Int32 ptr);
“Receive” which runs for the event that fires when a char is received looks like this (“esLink” is what I named my serial port inside this class) and you can see the Invoke of “WriteData” happening to write the char into the textbox’s .Text property, which also “grants the right” (I know that’s’ the wrong thing to say) to write the text into the label on the same UI thread in the “WriteData” function below it:
private void Recieve(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
byte recieved_data;
// Collecting the characters received to our 'buffer' (string).
while (esLink.BytesToRead > 0)
{
recieved_data = (byte)esLink.ReadByte();
// add it to the circular buffer
rxBuffer[nextBufferInputPoint] = recieved_data;
if (++nextBufferInputPoint >= RX_BUFFER_SIZE)
nextBufferInputPoint = 0;
// then put it in the text box for logging
logBox.Invoke(new UpdateUiTextDelegate(WriteData), recieved_data, nextBufferInputPoint);
}
}
private void WriteData(byte text, Int32 ptr)
{
// Assign the value of the recieved_data to the TextBox and label.
if (comLogging)
{
logBox.Text += (char)text;
inPtrLbl.Text = ptr.ToString();
}
}
So, all this works like a charm, really. As long as I declare the variable in the class to be the same type as what I’m passing in. But I want to pass (almost) anything with a .Text property to it so I have more flexibility in designing my GUI. I tried declaring the passed item as an Object, it gets there but the IDE complains that the object doesn’t have a .Text property. I tried declaring it as something with a .Text property and then “changing” it with a “new” but that didn’t work either. I said, ok, I’ll limit it to three types and create overloaded methods for the three types. The problem there is I could only make that work if I declared the three different types at the top and only used one (and set some kind of control variable to decide which one to use when writing to the UI control).
I’m thinking there has to be an easier way. In principle, I want to declare a generic object that I can turn into anything based on what I pass in and access its .Text property. At the very least, creating an overloaded method for each type (realistically there might be 4 or 5 different types only) would be acceptable (but not ideal) and I could live with that.
(I hope I have explained this well, sorry if not...)
Thanks,
-Vin
Honestly it's a little weird for a serial port library to have a dependency on a UI control (see separation of concerns). I'd suggest you set things up so the caller can pass a delegate instead.
Action<char> _logHandler;
public void TurnOnLogging(Action<char> logHandler)
{
comLogging = true;
_logHandler = logHandler;
}
Then, when you have data to log, call the delegate.
private void WriteData(byte text)
{
if (comLogging)
{
_logHandler((char)text);
}
}
This way the caller can decide how the contents are displayed. They can use a control that has a Text property, or a different type of control if they want to. Or maybe they might not want to use a textbox, or a winforms control at all, but maybe log it to a file.
obj.TurnOnLogging( x => TextBox1.Text += x.ToString() );
Or
obj.TurnOnLogging( x => SomeOtherControl1.Caption += x.ToString() );
Or
obj.TurnOnLogging( x => _logger.Write(x) );
You might also consider getting rid of your unusual mechanism in favor of something more idiomatic, such as a custom event.
You may define the type (of the parameter?) as "Control" (System.Windows.Forms.Control), as most UI control classes are derived from this class. Actually, the Control class has really a large number of properties, such as "Text", "Location", "Size", "Parent", etc.
See https://learn.microsoft.com/dotnet/api/system.windows.forms.control

Local variable vs private field effeciency

Is there like a rule of thumb about when to go either over the other?
Im curious because i have a dilemma here, where i have a very frequently used method, return a custom class type that is rather large. Im wondering if it wouldnt be cheaper to hold an instance of this custom class in a field, and then in the method just change and return it every time, rather than creating a whole new object as would be the case if i had a new class instance created in the method every time.
The main difference between returning a newly created instance of a class and returning a field is enormous: in the latter case, the instance is shared because all clients receive a pointer to the same instance. That means: whenever any of the clients (or the original creator of the instance) changes something in the instance, all clients will now see all those changes. In the former case, all instances are different, and changes affect only the current client.
So take a really close look at the requirements and find out which of the behaviors is required. Getting them wrong can have devastating effects.
What you seem to ask for is a so called lazy field. You declare it as System.Lazy<> like so
private System.Lazy<YourClass> mYourClassInstance;
...
mYourClassInstance = new System.Lazy<YourClass>(() => new YourClass());
and then you can get the instance via
mYourClassInstance.Value
anywhere you want but the value (instance) is only created once.

Is it a good practice to perform initialization within a Property?

I have a class PluginProvider that is using a PluginLoader component to load plugins (managed/native) from the file system. Within the PluginProvider class, there is currently defined a property called 'PluginTypes' which calls the 'InitializePlugins' instance method on get().
class PluginProvider
{
IEnumerable<IPluginType> PluginTypes
{
get
{
//isInitialized is set inside InitializePlugins method
if(!isInitialized)
{
InitializePlugins(); //contains thread safe code
}
//_pluginTypes is set within InitializePlugins method
return _pluginTypes;
}
}
}
I am looking at refactoring this piece of code. I want to know whether this kind of initialization is fine to do within a property. I know that heavy operations must not be done in a property. But when i checked this link : http://msdn.microsoft.com/en-us/library/vstudio/ms229054.aspx , found this " In particular, operations that access the network or the file system (other than once for initialization) should most likely be methods, not properties.". Now I am a bit confused. Please help.
If you want to delay the initialization as much as you can and you don't know when your property (or properties) will be called, what you're doing is fine.
If you want to delay and you have control over when your property will be called the first time, then you might want to make your method InitializePlugins() public and call it explicitly before accessing the property. This option also opens up the possibility of initializing asynchronously. For example, you could have an InitializePluginsAsync()that returns a Task.
If delaying the initialization is not a big concern, then just perform the initialization within the constructor.
This is of course a matter of taste. But what i would do depends on the length of the operation you're trying to perform. If it takes time to load the plugins, i would create a public method which any user would need to call before working with the class. A different approach would be to put the method inside the constructor, but IMO constructors should return as quickly as possible and should contain field / property initialization.
class PluginProvider
{
private bool _isInitialized;
IEnumerable<IPluginType> PluginTypes { get; set;}
public void Initialize()
{
if (_isInitialized)
{
return;
}
InitializePlugins();
_isInitialized = true;
}
}
Note the down side of this is that you will have to make sure the Initialize method was called before consuimg any operation.
Another thing that just came to mind backing this approach is exception handling. Im sure you wouldn't want your constructorcto be throwing any kind of IOException in case it couldn't load the types from the file system.
Any initialization type of code should be done in the constructor, that way you know it will be called once and only once.
public class PluginProvider
{
IEnumerable<IPluginType> PluginTypes
{
get
{
return _pluginTypes;
}
}
public PluginProvider()
{
InitializePlugins();
}
}
What you are doing there is called lazy initialization. You are postponing doing a potentially costly operation until the very moment its output is needed.
Now, this is not an absolute rule. If your InitializePlugins method takes a long time to complete and it might impact user experience, then you can consider moving it into a public method or even making it asynchronous and call it outside of the property: at app startup or whenever you find a good moment to call a long-lasting operation.
Otherwise, if it's a short lived one-time thing it can stay there. As I said, not an absolute rule. Generally these are some guidelines for whatever applies to a particular case.

Using XmlDocument.Save() Effectively

I'm working with a .XML document in C# to which I'm selecting nodes from, adding nodes to, and deleting nodes many, many times over a span of my code.
All of the XML editing of this document is contained within a class, which other classes call to.
Since the Data Access class has no way of telling if the classes using it are done with editing the document, it has no logic as to if/when to save.
I could save after every modification of the document, but I'm concerned with performance issues.
Alternatively I could just assume/hope that it will be saved by the other classes that use it (I created a one-line public method to save the document, so another class can request a save).
The second option concerns me as I feel like I should have it globally enforced in some manner to avoid it being called upon and modifications not being committed. To this point there will never be a case where a rollback is needed; any change is a change that should be committed.
Does .Net (Or coding design) have a way to balance performance and safety in such a situation?
If you always want to save the changes (just don't know when) then you could add the save command to the class destructor. This way you know the changes will always be saved.
If you need additional help or want an example please leave a comment, otherwise select an answer as correct.
Update: It has been brought to my attention that the class destructor may fire after other objects (like a FileStream) have already been disposed.
I recommended that you test for this condition in your destructor and also that you implement and use the IDisposable interface. You can then subscribe to the either the Application.Exit event or Application.ApplicationExit event and call dispose there.
Be sure to keep the code in the destructor (but make sure you have it in a try block) in case the program crashes or there is some other, unexpected exit.
Basically your question says i all: You need to save, but you don't know when, as the knowledge about the savepoints is otside your class.
My recommendation is to wrap your calls - assuming you have something like public void MyClass.SomeEditing(int foo), create a wrapper like public void MyClass.SomeEditing(int foo, bool ShouldSave) with shouldsave defaultingto true.
This way, a consumer of your class can decide, wether he wants an immediate save or not, chosing false if he knows, an immediately following other edit will cause the save. Existing code, which calls the "old" API is protected by the default of "save imediately"

How to modify TaskDialog's Show() call to be blocking and return a value when closed?

I'm using the WindowsAPICodePack's TaskDialog implementation, but it bugs me that I have to listen to click handlers on its buttons for even the more basic implementations. I'd like to convert/wrap it so that like the old MessageBox it blocks until closed and then returns a value based on what was done. Is there anything I can read for the basics on how to do this? I just have no idea where to even start, as I am admittedly not that familiar with the Win32 underpinnings.
In case it helps someone, after some reading I figured out that the Show call is blocking already. In order to return a value, I implemented a base class ExtendedTaskDialog<T> which contains a TaskDialog and contains a helper Show(Window) method in order to assign the TaskDialog's parent, and an abstract public T Show(Window) method. Actual dialogs derive from this, and derive their own enum to supply as the base type, like MyDialog : ExtendedTaskDialog<MyDialogResult>. Then, internally, MyDialog's buttons' Click handlers set the result before calling the Close method of the the internal TaskDialog.

Categories