Adding buttons by a function - c#

I want to add a button, using a function that takes all the arguments in one line, to keep it clean. But if I try to add the button via This.Controls.Add, I get an error because the function is static. What should I write instead of This (something like Form1.Controls.Add) so I can do everything in one function?

You could take the form as an argument to the static function:
public static void CreateButton(Form targetForm, param1, param2, ...) {
Button b = new Button();
...
targetForm.Controls.Add(b);
}
...but unless this method is going to be used to add buttons to a variety of forms, I don't see the advantage of making it static like this. It seems like a sort of OO anti-pattern. I would probably make it non-static and use this.

I would just have your function return the button:
//Usage
this.Controls.Add(CreateButton(...));
//Function def
public static Button CreateButton(...)
{
Button createdButton = new Button();
...
return createdButton;
}
Assignment returns the result of the assignment (so you can chain them). So to inline the assignment:
//With a variable (I did *not* say it was good practice to do this)
this.Controls.Add(myVar = CreateButton(...));

Related

Noobish Does Not Exist in the current context

Why i cannot call this one? ;(
public void StartNewGame()
{
Button GamePanelHideButton = new Button();
}
public void GamePanelHideButtonClick()
{
GamePanelHideButton.Visible = !GamePanelHideButton.visible;
}
GamePanelHideButton does not exist in context :( although its created before.
Your creation of the button is scoped within startnewgame() and is not accessible to method GamePanelHideButtonClick
Move the GamePanelHideButton variable outside of both methods.
Try this
public Button GamePanelHideButton;
public void StartNewGame()
{
GamePanelHideButton = new Button();
}
public void GamePanelHideButtonClick()
{
GamePanelHideButton.Visible = !GamePanelHideButton.visible;
}
GamePanelHideButton is a local variable - it only "exists" while the StartNewGame method is actually executing, and the only place you can actually refer to it is from inside the StartNewGame method. You should make this a field (class-wide variable).
Also, your statement that "it's created before" it's used is decidedly not true (or, at least, not necessarily true). There's nothing that'll guarantee that the two methods you show will be executed in any particular order - you could execute them in any order you feel like for all the compiler knows.
Moved this Button GamePanelHideButton = new Button(); outside any method and it worked, thank u all serious people for help.
Button GamePanelHideButton = new Button();

Change Textbox object to Static

I have little experience in C#, mostly playing with it as a hobby, and I was wondering what I needed to do to change a textbox from non-static to static.
In Visual Studio 2012, I'm trying to add a line of text using the method textbox1.AppendText("Text");, and it won't work because the textbox isn't static, while the method trying to write the code is static. I can't find the line of code where the textbox is initialized in my code, nor have I found an option in the properties that allows me to change that.
Is there a work-around, or do I need to make it static? And if I need to make it static, how would I do that? I'm at a loss.
Thank you for your help!
EDIT: adding code sample. The method below is called from a second form, same from which the value of x is determined.
public static void getMethod(int x)
{
if (x > 4)
{
textbox1.AppendText("Text");
}
else
{
textbox1.AppendText("Other text");
otherVariable = x;
}
}
It's not clear from your post which GUI framework you're using. Both Winforms and WPF have a TextBox class.
But, to the point of your question: you could in the object where the TextBox is declared and created, also have a static field to which you assign that reference. But that would be a poor design choice, IMHO.
It's not clear what your static code is doing, where it's declared, or who called it (another failing of your question is that you did not provide any code, never mind a concise, complete code example), but assuming the static method is not in the UI object that owns the TextBox instance itself (if it is, then you just need to make the method non-static), the the correct way to address this would be for the UI object that does know about the TextBox instance to have some public method or property used to set the text, and then for the code that invokes your static method to pass the reference of that UI object to the static method, so that it can use the member you added.
For example:
class Form1 : Form
{
public string FieldText
{
get { return textBox1.Text; }
set { textBox1.Text = value; }
}
}
and elsewhere:
static void SomeMethod(Form1 form)
{
// ...do some stuff...
form.FieldText = "some text";
// ...do some other stuff...
}
In your specific scenario, you seem to have two forms: one containing the textbox1 member, and another that passes an int value to a method, where you want to be able to add some text to the TextBox1 based on the value.
In that case, it would look more like this:
class Form1 : Form
{
public void AppendFieldText(string text)
{
textbox1.AppendText(text);
}
}
and in the static method:
public static void getMethod(int x, Form1 form)
{
if (x > 4)
{
form.AppendFieldText("Text");
}
else
{
form.AppendFieldText("Other text");
otherVariable = x;
}
}
Naturally, the caller of the getMethod() method will need the reference for the form parameter; you will have to pass that somehow to that second form which is calling this method, so that it can pass it to the method.
Note that in both of my examples, I have not exposed the TextBox object itself. You should follow this example, exposing only the minimum amount of functionality needed in order to get the job done. This helps ensure that the TextBox object doesn't wind up getting used in appropriately by some other code, and especially helps ensure that your classes remain reasonably decoupled.
On that latter point, I will mention that your code example is still pretty bare. There are other techniques which can solve this problem with even less coupling between the types. But again, lacking a good code example, it's not possible to know for sure what would work, never mind what would be best.
The above example is appropriate, given the information you've shared.
If you would like to edit your question to provide better, more specific detail, a better, more specific answer could be provided.
you can do something like below
private void button3_Click(object sender, EventArgs e)
{
getMethod(textBox1,5);
}
public static void getMethod(TextBox textbox1,int x)
{
if (x > 4)
{
textbox1.AppendText("Text");
}
else
{
textbox1.AppendText("Other text");
otherVariable = x;
}
}
Textboxes aren't static. And you can't make them static, they are all instanciated. The name of your textbox is the instance name.
So just use the text property on the instance of the text box.
textbox1.Text = "Text";
If you want to Append one just do:
textbox1.Text = String.Concat(Textbox1.Text, "more text");
same thing about could also be seen as:
textbox1.Text = textbox1.Text + "more text";

C# - Update GUI datagridview from another thread using delegate

I'm trying to update a datagridview with some data calculated in a different class and thread, using a delegate. Unfortunately I'm having trouble with a variety of different errors, depending on the approach I try.
The code I am trying to execute in the form thread looks like this:
public partial class AcquireForm : Form
//
// ...
//
// update the grid with results
public delegate void delUpdateResultsGrid(int Index, Dictionary<string, double> scoreCard);
public void UpdateResultsGrid(int Index, Dictionary<string, double> scoreCard)
{
if (!this.InvokeRequired)
{
//
// Some code to sort the data from scoreCard goes here
//
DataGridViewRow myRow = dataGridViewResults.Rows[Index];
DataGridViewCell myCell = myRow.Cells[1];
myCell.Value = 1; // placeholder - the updated value goes here
}
}
else
{
this.BeginInvoke(new delUpdateResultsGrid(UpdateResultsGrid), new object[] { Index, scoreCard});
}
}
Now, I need to get this method to run from my other thread and class. I have tried:
public class myOtherClass
//
// ...
//
private void myOtherClassMethod(int myIndex)
{
// ...
AcquireForm.delUpdateResultsGrid updatedelegate = new AcquireForm.delUpdateResultsGrid(AcquireForm.UpdateResultsGrid);
updatedelegate(myIndex, myScoreCard);
}
Unfortunately this gives an "Object reference is required for the non-static field, method, or property AcquireForm.UpdateResultsGrid(int, System.Collections.Generic.Dictionary)" error. I seem to be unable to reference the UpdateResultsGrid method at all...
I have noticed that
public class myOtherClass
//
// ...
//
private void myOtherClassMethod(int myIndex)
{
// ...
AcquireForm acquireForm = new AcquireForm();
acquireForm.UpdateResultsGrid(myIndex,myScoreCard);
}
does not throw any errors when compiling, but it tries to create a new form and that is something I do not want to do. I don't want to create a new instance of AcquireForm, I want to reference the pre-existing one, if that's possible.
I have also tried making the UpdateResultsGrid method static, but this throws up problems with several things incuding the use of "this.(anything)".
I've also tried moving the majority of the UpdateResultsGrid method into myOtherClassMethod, leaving behind in the AcquireForm class just the delegate. Again, this does not work because many of the references to UI objects break (there aren't any dataGridViews in scope).
I'm starting to run out of ideas here. Unfortunately I'm rather new to C# (as you can probably tell), and I'm editing someone else's code rather than writing my own entirely from scratch. If anyone could offer some advice on this problem it'd be most appreciated.
Make sure your objects are communicating with each other: Your myOtherClass is going to have to know about the AcquireForm object - you can't just create a new one (as you've discovered). You'll need to pass the AcquireForm object into the myOtherClass object (myOtherObject.SetForm(myAcquireForm, for example) and reference it when you need to.
In case you're having issues with invoking this might be of help - how I invoke a "next" button click:
BeginInvoke(new Action(()=>button_next_Click(null,null)));
Moreover, it sounds like maybe this should not be separate classes and you should be utilising a BackgroundWorkder instead.

Can you call a class' method when you declare the object?

I have a class, where I declare it, but that class gets added as an item to another bigger class. Is there a way to call the Init() method in the same statement as the call? Similar to defining public properties/variables when you call the constructor. I don't want to call the Init() method in the constructor because it messes with the WPF Designer.
FitsView fv = new FitsView();
fv.Init();
You could use a static function to do that:
public static FitsView CreateFitsView()
{
var fv = new FitsView();
fv.Init();
return fv;
}
Then you simply call that static function instead of new FitsView()
You could also try hooking a custom event to your FitsView if it knows when it's ready to be initialized?
And use it like this:
FitsView fv = new FitsView();
fv.someCustomEvent += (o,e) => { fv.Init(); };
If the designer gets problematic because of your init method there are two reasons I can think of:
It is because something you do in Init method needs locality of your application (reading resources or files or using hardware)
Calling your Init method needs some external assemblies to be loaded dynamically.
For the first matter you may want to check:
For your class: Is there a DesignMode property in WPF?
For your view model: http://blog.laranjee.com/how-to-get-design-mode-property-in-wpf/
Also people in here pointed out this bug so please beware (hosting wpf in winforms): https://connect.microsoft.com/VisualStudio/feedback/details/620001/system-componentmodel-designerproperties-getisindesignmode-does-not-work-if-the-wpf-is-hosted-on-a-winform#tabs
For the second matter you can wrap your Init method in another let's say InitWrapper and do your design mode check for wrapper method.
Similar to the StringBuilder.Append you could alter Init to return a reference to the object.
Public FitsView Init()
{
//Do stuff
return this;
}
Then:
FitsView fv = new FitsView().Init();

C# Call function in a class from another class

I'll start of by saying I'm not a developer. Yes this is a c# nightmare. But this is a one time tool and thats it. Quick and Dirty it just needs to work and thats it.
I have the following code:
public string[] get_status(string local_fname)
{
var dts_doc = new HtmlAgilityPack.HtmlDocument();
dts_doc.Load(local_fname);
//Pull the values
var ViewState = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[1]/input[4]/#value[1]");
var EventValidation = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[2]/input[1]/#value[1]");
string ViewState2 = ViewState.Attributes[3].Value;
string EventValidation2 = EventValidation.Attributes[3].Value;
//Display the values
//System.Console.WriteLine(ViewState.Attributes[3].Value);
//System.Console.WriteLine(EventValidation.Attributes[3].Value);
//System.Console.ReadKey();
return new string[] { ViewState2, EventValidation2 };
}
I want to call get_status from a button on my Main.cs which will show 2 Message Boxes with ViewState2 and EventValidation2.
Again, I'm not a developer, this is probably the wrong way of doing things. But I just need a quick and dirty solution to get this job done once.
Make the function static by adding the static keyword to the function definition:
static public string[] get_status(string local_fname)
Use the class name to reference the function from your Main class.
try this:
foreach(string s in get_status(localFname))
{
MessageBox.Show(s);
}
As you said, it is quick and dirty and I stayed faithful to that paradigm.
And yes, if you need to acces another class, make the method static or just simply create an instance and call the method on it. I hope I have understood the problem correctly.
if you are using visual studio, go to the Button you want to click, double-click the button. This will create an eventhandler. In the eventhandler you should call the above method.
protected void Button1_Click(object sender, eventArgs e)
{
string local_fname = someValue;
string results[] = get_status(local_fname);
MessageBox.Show(results[0]);
MessageBox.Show(results[1]);
}

Categories

Resources