Calling non-static methods in a static method - c#

I am really stuck in some sort of static-hell that I've placed myself into. I have a server and client. The client asks the server for a list of lobbies. The client creates a graphical lists of buttons for each lobby. Each lobby button has a reference to Matchmaking's static method JoinLobby as this seemed the most simple way to hook up n amount of lobby buttons.
However after a lobby button calls JoinLobby (static) I wanted the Matchmaking class to toggle off some UI elements that are public but not static. I want to avoid making these elements static if possible, because I am using Unity and it breaks the workflow of using Unity's built-in drag-and-drop reference creator.
public class LobbyButton{
public Button button;
public Text name;
public void JoinLobby(){
Matchmaking.JoinLobby(name.text);
}
}
public class Matchmaking{
public LobbyList lobbyList; // UI list element
public static void JoinLobby(string name){
JoinServerLobby(name);
lobbyList.Hide(); // can't do this, lobbyList not static
}
}
I've run in to this situation a few times and always end up doing some work-around or total redo. But I am wondering if there is a more common way of "getting out" of this static call.

In my opinion you have something wrong with your design.
Basically static means, that current member is a part of type, non an instance, thus mixing them to achieve some result, looks odd.
I think that you should inject Matchmaking to the LobbyButton button, store it as a field and reference to the non-static JoinLobby. I would leave static method to either utility tasks or generic functions, not related to the specific functionality.

Each lobby button has a reference to Matchmaking's static method JoinLobby as this seemed the most simple way to hook up n amount of lobby buttons.
Don't do that then.
In the form that has the "lobby buttons", keep a private variable with a reference to a Matchmaking instance. In the click events, refer to this variable.
You can also use the Tag property of buttons to give them an identifier, and hook them all up to the same click handler. There you check the Tag of the sender.

Related

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
}

Global objects or not?

I have WinForms app and multiple forms and want to use ErrorProvider component on each of them EDIT: to check if user input is OK (for example if entered number is in the range etc...) It seems to me useless to drop this component onto each and every form. What if I make one global object (or how to call it) and use it on every form?
My idea:
namespace MyApplication {
static class Program {
public static ErrorProvider EP = new ErrorProvider();
...
And then in that individual form to handle Validating and Validated events:
private void txtBox1_Validating(object sender, System.ComponentModel.CancelEventArgs e) {
if (txtBox1.Text != "correct text") {
e.Cancel = true;
Program.EP.SetError(txtBox1, "You have error in your input");
...
Is this correct approach or should I do it somehow else?
And if I need more global objects, maybe I should put them all together to some separate static class and in the Program create just this one (?)
Thanks.
This approach is valid as long as your individual forms are never running concurrently or your error provider is re-entrant, and your error provider does not need a permanent link back to your forms. From the example that you show it appears that your provider requires you to pass the control on which to set the error state, so it has a good chance of being re-entrant.
It is ok to have global object but I would rather make it a static stateless class if possible. Statelessness will allow for easy thread safety. It is common across .NET to have global (within namespace) static classes, for example FileInfo or Convert.
If you only need a few global methods and they operate on UI elements you can also write some extension methods for System.Windows.Controls.Control or even System.Windows.Controls.TextBox if that's the only control you want. This will give you a bit nicer code:
txtBox1.Validate("correct text", "You have error in your input");
Extension method could look like this:
public static class MyExtension
{
public static void Validate(this TextBox myTextBox, string correctText, string error)
{
if(myTextBox.Text != correctText)
Console.WriteLine(string.Format("{0} [{1} == '{2}']", error, myTextBox.Name, myTextBox.Text));
}
}
Which would give you this message in the console:
You have error in your input [txtBox1 == 'some text']
Look at extension methods documentation if you need more info.
I think you can create a new class that inherits textbox class and add your validations there, then create a new control which is your class and use it where ever you need, in this case you will edit/modify your validations in one place later on.
I f you have very different validations create 2 classes for example: NumericTextBox and StringTextBox

C Sharp/ASP.NET: OOP Good Practice Question

I'm currently in the process of working in a class design for a web application I'm building. I'm relatively new to OOP (although I have done some). For the most part I'm fairly confident that I know what I'm doing in the paradigm: I know that it's not good practice for one class to access the internal workings of another class, that unsafe static methods are unsafe because they can modify global state, and that generally speaking, the more purely functional and modular I can keep my code the better off I will be.
I'm a little unsure of what to do in this situation though. I have multiple web pages which all have their own GridView control. Some logic will go through each row and change the color of the row based on certain conditions. Would it be considered bad practice, for example, to keep one static class encapsulating these style changes, which will be accessed by every page? Technically this means that this class would be modifying a member of another class. How should I go about this? I would prefer not to duplicate my code through each class, as I try to adhere to the DRY principle as much as possible.
EDIT: Here's what I'm thinking.
public static class RowStyle
{
public static void SetRed(GridViewRow row)
{
row.BackColor = Color.Red;
}
// More methods here
}
And each page will pass many GridViewRows to this class, and then have them modified.
Generally, static methods are not so much of a problem if they dont modify static state. Therefore, as long as everything it needs is either encapsulated in the method, or passed in via params then there is less of an issue.
Eg, following your example, the following would IMO be fine
public static class Colorizer
{
public static void Colorize(GridView gv)
{
// do you're funky logic here.
}
}
And use that method in each of your pages that need the logic.
However, this would be bad bad bad:
public static class Colorizer
{
private static bool haveIAlreadyColorized = false;
public static void Colorize(GridView gv)
{
if(!haveIAlreadyColorized)
// do you're funky logic here.
}
}
I'd recommend creating a custom UserControl containing your GridView and add all associated logic there. That is the best way to do it within the ASP.NET platform.
If same color codes you will follow then, you can follow this:
Create a common class. Make it static.
Create a method as that will be called in the rowdatabound event and based on event you can change color
I think it would be fine to have a static class with a method like this:
public static System.Drawing.Color GetRowColor(GridRow row)
...
If the rules which govern the value of the color are global, then this is proper.
I would encapsulate the style changes in a single place (web.config would be my choice), and create a helper method that takes a GridView instance as parameter. That helper method's sole purpose in life would be read the style info from the config file, to apply it to the passed GridView instance.
Any pages containing a GridView to which those style changes should be applied, would call the helper method.

Why to use events somewhere where method is enough?

I read some events tutorial and just do not get what is the benefit in simple code like this..method should be used the same way:
class Bulb
{ public delegate void handler();
public event handler Glowing;
...
Glowing+=SomeMethod;
private void TurnOn
{
Glowing();
}
private void SomeMethod
{
}
}
Simply Events allow others using your code to perform some custom Implementation they want when that Event occurs (when Bulb is Glowing).
Simply calling your method won't tell anybody that something has happened.
Events are very basic Element of any Event Driven Programming
If your program doesn't need to tell about an event you don't need to implement such Functionality. However having such functionality has benefits.
For Example when using a List Class you dont know when an Item got added to it (if at some point some other code does that) but in a ObservableCollection you get notifications when Items are Added or Removed.
An event is a message sent by an object to signal the occurrence of an action. The action could be caused by user interaction, such as a mouse click, or it could be triggered by some other program logic.
The idea is that a different class which can hold Three different Bulbs can get notified by the event (if it implements a handler) that the light has been turned on and is Glowing.
So the benefit does not reside in the simply class but in what ever classes/objects are going to be holding/using instances of the Bulb class.
Hope that made some sense :)
Events over methods become handy when you have a class dependency that needs to know or be notified about a stateful change:
public class Lamp
{
Bulb inThelamp = new Bulb();
inTheLamp.Glowing += myLampMethod;
// If these arguments have been defined for this event that is
public void myLampMethod(object sender, EventArgs e)
{
// Code to react to the light suddenly being on
}
}
This allows the Lamp class to recognize that something has turned the bulb on. In many cases it will be through some action in the Lamp (click, pushknob, etc). But in some cases it could be an external class that calls a public Bulb property directly without using the Lamp itself (such is if(PowerCompany.BillsPaid) Lamp.BulbInTheLamp.TurnedOn();). This is all assuming that the modifiers are set to allow this kind of access.
The point is that it allows notification of an occurrence rather than requiring that a particular method be called manually each time you want an action to occur.

Best way to access a control on another form in Windows Forms?

First off, this is a question about a desktop application using Windows Forms, not an ASP.NET question.
I need to interact with controls on other forms. I am trying to access the controls by using, for example, the following...
otherForm.Controls["nameOfControl"].Visible = false;
It doesn't work the way I would expect. I end up with an exception thrown from Main. However, if I make the controls public instead of private, I can then access them directly, as so...
otherForm.nameOfControl.Visible = false;
But is that the best way to do it? Is making the controls public on the other form considered "best practice"? Is there a "better" way to access controls on another form?
Further Explanation:
This is actually a sort of follow-up to another question I asked, Best method for creating a “tree-view preferences dialog” type of interface in C#?. The answer I got was great and solved many, many organizational problems I was having in terms of keeping the UI straight and easy to work with both in run-time and design-time. However, it did bring up this one niggling issue of easily controlling other aspects of the interface.
Basically, I have a root form that instantiates a lot of other forms that sit in a panel on the root form. So, for instance, a radio button on one of those sub-forms might need to alter the state of a status strip icon on the main, root form. In that case, I need the sub-form to talk to the control in the status strip of the parent (root) form. (I hope that makes sense, not in a "who's on first" kind of way.)
Instead of making the control public, you can create a property that controls its visibility:
public bool ControlIsVisible
{
get { return control.Visible; }
set { control.Visible = value; }
}
This creates a proper accessor to that control that won't expose the control's whole set of properties.
I personally would recommend NOT doing it... If it's responding to some sort of action and it needs to change its appearance, I would prefer raising an event and letting it sort itself out...
This kind of coupling between forms always makes me nervous. I always try to keep the UI as light and independent as possible..
I hope this helps. Perhaps you could expand on the scenario if not?
The first is not working of course. The controls on a form are private, visible only for that form by design.
To make it all public is also not the best way.
If I would like to expose something to the outer world (which also can mean an another form), I make a public property for it.
public Boolean nameOfControlVisible
{
get { return this.nameOfControl.Visible; }
set { this.nameOfControl.Visible = value; }
}
You can use this public property to hide or show the control or to ask the control current visibility property:
otherForm.nameOfControlVisible = true;
You can also expose full controls, but I think it is too much, you should make visible only the properties you really want to use from outside the current form.
public ControlType nameOfControlP
{
get { return this.nameOfControl; }
set { this.nameOfControl = value; }
}
After reading the additional details, I agree with robcthegeek: raise an event. Create a custom EventArgs and pass the neccessary parameters through it.
Suppose you have two forms, and you want to hide the property of one form via another:
form1 ob = new form1();
ob.Show(this);
this.Enabled= false;
and when you want to get focus back of form1 via form2 button then:
Form1 ob = new Form1();
ob.Visible = true;
this.Close();
I would handle this in the parent form. You can notify the other form that it needs to modify itself through an event.
Use an event handler to notify other the form to handle it.
Create a public property on the child form and access it from parent form (with a valid cast).
Create another constructor on the child form for setting form's initialization parameters
Create custom events and/or use (static) classes.
The best practice would be #4 if you are using non-modal forms.
You can
Create a public method with needed parameter on child form and call it from parent form (with valid cast)
Create a public property on child form and access it from parent form (with valid cast)
Create another constructor on child form for setting form's initialization parameters
Create custom events and/or use (static) classes
Best practice would be #4 if you are using non-modal forms.
With the property (highlighted) I can get the instance of the MainForm class. But this is a good practice? What do you recommend?
For this I use the property MainFormInstance that runs on the OnLoad method.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LightInfocon.Data.LightBaseProvider;
using System.Configuration;
namespace SINJRectifier
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
UserInterface userInterfaceObj = new UserInterface();
this.chklbBasesList.Items.AddRange(userInterfaceObj.ExtentsList(this.chklbBasesList));
MainFormInstance.MainFormInstanceSet = this; //Here I get the instance
}
private void btnBegin_Click(object sender, EventArgs e)
{
Maestro.ConductSymphony();
ErrorHandling.SetExcecutionIsAllow();
}
}
static class MainFormInstance //Here I get the instance
{
private static MainForm mainFormInstance;
public static MainForm MainFormInstanceSet { set { mainFormInstance = value; } }
public static MainForm MainFormInstanceGet { get { return mainFormInstance; } }
}
}
I agree with using events for this. Since I suspect that you're building an MDI-application (since you create many child forms) and creates windows dynamically and might not know when to unsubscribe from events, I would recommend that you take a look at Weak Event Patterns. Alas, this is only available for framework 3.0 and 3.5 but something similar can be implemented fairly easy with weak references.
However, if you want to find a control in a form based on the form's reference, it's not enough to simply look at the form's control collection. Since every control have it's own control collection, you will have to recurse through them all to find a specific control. You can do this with these two methods (which can be improved).
public static Control FindControl(Form form, string name)
{
foreach (Control control in form.Controls)
{
Control result = FindControl(form, control, name);
if (result != null)
return result;
}
return null;
}
private static Control FindControl(Form form, Control control, string name)
{
if (control.Name == name) {
return control;
}
foreach (Control subControl in control.Controls)
{
Control result = FindControl(form, subControl, name);
if (result != null)
return result;
}
return null;
}
#Lars, good call on the passing around of Form references, seen it as well myself. Nasty. Never seen them passed them down to the BLL layer though! That doesn't even make sense! That could have seriously impacted performance right? If somewhere in the BLL the reference was kept, the form would stay in memory right?
You have my sympathy! ;)
#Ed, RE your comment about making the Forms UserControls. Dylan has already pointed out that the root form instantiates many child forms, giving the impression of an MDI application (where I am assuming users may want to close various Forms). If I am correct in this assumption, I would think they would be best kept as forms. Certainly open to correction though :)
Do your child forms really need to be Forms? Could they be user controls instead? This way, they could easily raise events for the main form to handle and you could better encapsulate their logic into a single class (at least, logically, they are after all classes already).
#Lars: You are right here. This was something I did in my very beginning days and have not had to do it since, that is why I first suggested raising an event, but my other method would really break any semblance of encapsulation.
#Rob: Yup, sounds about right :). 0/2 on this one...
You should only ever access one view's contents from another if you're creating more complex controls/modules/components. Otherwise, you should do this through the standard Model-View-Controller architecture: You should connect the enabled state of the controls you care about to some model-level predicate that supplies the right information.
For example, if I wanted to enable a Save button only when all required information was entered, I'd have a predicate method that tells when the model objects representing that form are in a state that can be saved. Then in the context where I'm choosing whether to enable the button, I'd just use the result of that method.
This results in a much cleaner separation of business logic from presentation logic, allowing both of them to evolve more independently — letting you create one front-end with multiple back-ends, or multiple front-ends with a single back-end with ease.
It will also be much, much easier to write unit and acceptance tests for, because you can follow a "Trust But Verify" pattern in doing so:
You can write one set of tests that set up your model objects in various ways and check that the "is savable" predicate returns an appropriate result.
You can write a separate set of that check whether your Save button is connected in an appropriate fashion to the "is savable" predicate (whatever that is for your framework, in Cocoa on Mac OS X this would often be through a binding).
As long as both sets of tests are passing, you can be confident that your user interface will work the way you want it to.
This looks like a prime candidate for separating the presentation from the data model. In this case, your preferences should be stored in a separate class that fires event updates whenever a particular property changes (look into INotifyPropertyChanged if your properties are a discrete set, or into a single event if they are more free-form text-based keys).
In your tree view, you'll make the changes to your preferences model, it will then fire an event. In your other forms, you'll subscribe to the changes that you're interested in. In the event handler you use to subscribe to the property changes, you use this.InvokeRequired to see if you are on the right thread to make the UI call, if not, then use this.BeginInvoke to call the desired method to update the form.
Step 1:
string regno, exm, brd, cleg, strm, mrks, inyear;
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
string url;
regno = GridView1.Rows[e.NewEditIndex].Cells[1].Text;
exm = GridView1.Rows[e.NewEditIndex].Cells[2].Text;
brd = GridView1.Rows[e.NewEditIndex].Cells[3].Text;
cleg = GridView1.Rows[e.NewEditIndex].Cells[4].Text;
strm = GridView1.Rows[e.NewEditIndex].Cells[5].Text;
mrks = GridView1.Rows[e.NewEditIndex].Cells[6].Text;
inyear = GridView1.Rows[e.NewEditIndex].Cells[7].Text;
url = "academicinfo.aspx?regno=" + regno + ", " + exm + ", " + brd + ", " +
cleg + ", " + strm + ", " + mrks + ", " + inyear;
Response.Redirect(url);
}
Step 2:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string prm_string = Convert.ToString(Request.QueryString["regno"]);
if (prm_string != null)
{
string[] words = prm_string.Split(',');
txt_regno.Text = words[0];
txt_board.Text = words[2];
txt_college.Text = words[3];
}
}
}
public void Enable_Usercontrol1()
{
UserControl1 usercontrol1 = new UserControl1();
usercontrol1.Enabled = true;
}
/*
Put this Anywhere in your Form and Call it by Enable_Usercontrol1();
Also, Make sure the Usercontrol1 Modifiers is Set to Protected Internal
*/
Change modifier from public to internal. .Net deliberately uses private modifier instead of the public, due to preventing any illegal access to your methods/properties/controls out of your project. In fact, public modifier can accessible wherever, so They are really dangerous. Any body out of your project can access to your methods/properties. But In internal modifier no body (other of your current project) can access to your methods/properties.
Suppose you are creating a project, which has some secret fields. So If these fields being accessible out of your project, it can be dangerous, and against to your initial ideas. As one good recommendation, I can say always use internal modifier instead of public modifier.
But some strange!
I must tell also in VB.Net while our methods/properties are still private, it can be accessible from other forms/class by calling form as a variable with no any problem else.
I don't know why in this programming language behavior is different from C#. As we know both are using same Platform and they claim they are almost same Back end Platform, but as you see, they still behave differently.
But I've solved this problem with two approaches. Either; by using Interface (Which is not a recommend, as you know, Interfaces usually need public modifier, and using a public modifier is not recommend (As I told you above)),
Or
Declare your whole Form in somewhere static class and static variable and there is still internal modifier. Then when you suppose to use that form for showing to users, so pass new Form() construction to that static class/variable. Now It can be Accessible every where as you wish. But you still need some thing more.
You declare your element internal modifier too in Designer File of Form. While your Form is open, it can be accessible everywhere. It can work for you very well.
Consider This Example.
Suppose you want to access to a Form's TextBox.
So the first job is declaration of a static variable in a static class (The reason of static is ease of access without any using new keywork at future).
Second go to designer class of that Form which supposes to be accessed by other Forms. Change its TextBox modifier declaration from private to internal. Don't worry; .Net never change it again to private modifier after your changing.
Third when you want to call that form to open, so pass the new Form Construction to that static variable-->>static class.
Fourth; from any other Forms (wherever in your project) you can access to that form/control while From is open.
Look at code below (We have three object.
1- a static class (in our example we name it A)
2 - Any Form else which wants to open the final Form (has TextBox, in our example FormB).
3 - The real Form which we need to be opened, and we suppose to access to its internal TextBox1 (in our example FormC).
Look at codes below:
internal static class A
{
internal static FormC FrmC;
}
FormB ...
{
'(...)
A.FrmC = new FormC();
'(...)
}
FormC (Designer File) . . .
{
internal System.Windows.Forms.TextBox TextBox1;
}
You can access to that static Variable (here FormC) and its internal control (here Textbox1) wherever and whenever as you wish, while FormC is open.
Any Comment/idea let me know. I glad to hear from you or any body else about this topic more. Honestly I have had some problems regard to this mentioned problem in past. The best way was the second solution that I hope it can work for you. Let me know any new idea/suggestion.

Categories