access textbox from external class - get no errors - c#

I have a project, designed with Visual Community 2015, based on Windows.Form.
I want to realized a simple Server program - using the msdn library:
https://msdn.microsoft.com/en-us/library/fx6588te%28v=vs.110%29.aspx
So I create a simple Form1 with the designer with a richTextbox (name: llog) and one button (click event pushthebutton), which called an external class AsynchronousSocketListener. after this, it should to be to call a methode logme() and a messagebox will pop-up (it works, I see this). But I cannot write into the richTextbox llog. I get no errors, but nothing is written into the box. I can remember, that it has something to do with the invoke or delegate problem. but I cant figure it out. I stuck here since 5 hours with no solution. Can anybody help me - what I have to do, to access the the box from the AsynchronousSocketListener() class? I dont know, why I get no errors!
You see my last attempt - I also try to parse the form as parameter on each methode call (nothing works) - but I cant believe, thats the right way...
ps: bad english, I know ...
// Form1.cs - I reduced it to the min - a window with a textbox and a button appears
namespace MyProject
{
public partial class Form1 : Form {}
public void pushthebutton() {
AsynchronousSocketListener srv = new AsynchronousSocketListener();
srv.StartListening();
}
}
// AsynchronousSocketListener.cs
namespace MyProject
{
public class AsynchronousSocketListener : Form1
{
// Thread signal.
public static ManualResetEvent allDone = new ManualResetEvent(false);
public Form1 form;
public AsynchronousSocketListener()
{
form = new Form1();
logme(this, "constructer");
}
public void logme(Form1 form, string s)
{
MessageBox.Show("inside logme");
if (llog.InvokeRequired)
{
// invoke needed
form.llog.Invoke((MethodInvoker)delegate { llog.AppendText("\r\n" + s); llog.ScrollToCaret(); });
}
else
{
// no invoke needed
llog.AppendText("\r\n" + s);
llog.ScrollToCaret();
}
}
}
}
// inside FormDesigner.cs - shortcut; box is public...
public System.Windows.Forms.RichTextBox llog;

I haven't used winforms in forever, so I don't know whether or not this is a good practice, but in AsynchronousSocketListener, all you're doing is instantiating a new form that is not tied to anything. You might want to actually pass your form into there
public AsynchronousSocketListener(Form1 parent)
{
form = parent;
logme(this, "constructer");
}
and in Form1
AsynchronousSocketListener srv = new AsynchronousSocketListener(this);
On a side note, I don't understand why AsynchronousSocketListener is inheriting from Form1 as seen in the line public class AsynchronousSocketListener : Form1 that doesn't seem to be accomplishing anything

Related

C# Get field from Main Form

I have a main form and I need in other class get or set field from Main Form. I created public property in Main Form:
public partial class MainForm : Form
{
public string get_txt()
{
return phone.Text; //phone - textbox
}
}
But in other class I can't get this property:
MessageBox.Show(MainForm.get_txt); //there error. It doesn't seemed get_txt property.
I'm sorry for this simpliest question, but I really don't know this. Everywhere wrote that simpliest way to do it - in class of Main Form create public property for needed private field in Main Form. What do I wrong?
So the MessageBox.Show(MainForm.get_txt) won't compile as you're trying to refer to a static property, not an instance method.
I'm not a winforms dev, so this is a bit of a guess:
Somewhere in your code you will have a call like var main = new MainForm(). On that instance i.e. main you will be able to call main.get_txt().
As a side note, given that you're working in C# it'd be good to name the method to something a little more idiomatic, perhaps public string GetPhoneNumber() or better yet make it a property:
public string PhoneNumber
{
get { return phone.Text; }
}
Make instance of MainForm and than call it.
Mainform _mainform=new Mainform();
MessageBox.Show(_mainform.Get_text);
Your MainForm is not static class, you can not use like that. If u want access the MainForm(methods or variables), you have to assing the variable.
MainForm mForm = new MainForm();
MessageBox.Show(mForm.getText());
Thanks to you all.
but when I create a new istance of Main Form all controls in it will be initializing like in my current Main Form?

How to change progress bar and textbox from another class

I've built an installer script for some software. I'm trying to make to such that my installation script (InstallationScript.cs) and Form GUI (Install.cs) are partitioned. However, when I try to update the form components from the InstallationScript class, it cannot resolve symbol, but yet can see methods like .Show(). I thought perhaps if I exposed a public reference to itself it would be able to see the instance of the form, but that doesn't seem to work either. Am I missing something here?
namespace Generic_Installer_Framework.gui {
public partial class Install : Form {
public static Install Self;
public Install() {
Self = this;
InitializeComponent();
}
public void InstallStep(int value, string message, string logMessage = "") {
Logger.Log(logMessage == "" ? message : logMessage);
installationProgressBar.Value = value;
installationRichTextBox.AppendText(message + "\n");
}
}
}
Other class:
namespace Generic_Installer_Framework{
class InstallationScript {
private readonly Form _installerForm = Install.Self;
public void Start() {
//This works
_installerForm.Show();
//This doesn't
_installerForm.InstallStep(0, "Starting...");
}
}
}
Thank you so much!
However, when I try to update the form components from the
InstallationScript class, it cannot resolve symbol, but yet can see
methods like .Show().
The problem is right here:
private readonly Form _installerForm = Install.Self;
You've declared "_installerForm" as the generic type of Form, which of course has no idea what you're talking about...
Change the type to Install, and all should be good:
private readonly Install _installerForm = Install.Self;
My guess that it can be because you run Start() method in a different Thread. You can try to pass this method inside a delegate :
public Action<int, string, string> InsStep = new Action<int, string, string>(InstallStep);
Try to call it in your InstallationScript class by installerForm.InsStep(0, "Starting...", "");
You can also benefit from using SynchronizationContext.Current property:
First you take it from your form :
SynchronizationContext sync = SynchronizationContext.Current;
Then you pass it to another Thread or whereever you want and use like:
sync.Post(delegate
{
// your updates here will be executed thread-safe
}, null);

How to save the value of the variable after closing the form

In WindowsForms I have an independent class Indicators.cs and a form Food. In the class I have a variable, which I'm changing in the form.
When I open the form, changing the variable, close the form and open it again (without closing the program), then the value of the variable is old. Why so?
Form:
namespace WF
{
public partial class Computer : Form
{
Indicators indicators = new Indicators();
public Computer()
{
if (indicators.isComputerAlreadyRunning == false)
indicators.isComputerAlreadyRunning = true;
}
}
}
Indicators.cs
namespace WF
{
class Indicators
{
public Indicators()
{
this.isComputerAlreadyRunning = false;
}
public bool isComputerAlreadyRunning;
}
}
Create a method in the form class that shows the form and returns a result. This is similar to the MessageBox.Show method. In the example below the FoodForm has a method called ShowForm. This method returns a custom class called FoodFormResult that has all the results needed from the form after it closes.
public FoodFormResult ShowForm()
{
return new FoodFormResult(
ShowDialog() == DialogResult.OK,
_indicators);
}
Every time the form class is created (ex. new FoodForm()), all the existing values in the form are lost.
Many ways to do this..You can create a delegate, save to form's resources, save to external file, save to settings/Appconfig file..So on..
And another but not much recommended for security reasons option is that : You can Create an internal or public static variable in main method of the application..Then when you need set to this variable..
And when you need to call that variable :
//Your main method example
static class Program
{
internal static bool AreYouOKAY = false;
// or public static bool as your needs
static void Main ()
{
........
}
/// And in your form
Program.AreYouOKAY = true;
// After your form closed.. from another form just call as above
if(Program.AreYouOKAY)
{
MessageBox.Show (" Yeah! I'm Ok!");
}

Windows Forms, Designer, and Singleton

I'm trying to work with Windows Forms and User Controls and thus far it's been nothing but a headache. I can't make the form or the controls static because the designer doesn't like that and when I use Singleton on my form and controls, the designer still throws errors at me.
My FormMain:
public partial class FormMain : Form
{
private static FormMain inst;
public static FormMain Instance
{
get
{
if (inst == null || inst.IsDisposed)
inst = new FormMain();
return inst;
}
}
private FormMain()
{
inst = this;
InitializeComponent();
}
MainScreen.cs:
public partial class MainScreen : UserControl
{
private static MainScreen inst;
public static MainScreen Instance
{
get
{
if (inst == null || inst.IsDisposed)
inst = new MainScreen();
return inst;
}
}
private MainScreen()
{
inst = this;
InitializeComponent();
}
If the constructor of MainScreen is public the program runs, but when I change it to private I now get an error in FormMain.Designer.cs saying "'Adventurers_of_Wintercrest.UserControls.MainScreen.MainScreen()' is inaccessible due to its protection level". It points to this line:
this.controlMainScreen = new Adventurers_of_Wintercrest.UserControls.MainScreen();
I think this is the instance of the class that the designer makes by default. Should I ditch the designer? Or is there a way around this? Or is there another way to make class properties accessible without using Singleton (since I can't seem to make the form or controls static)? Any help would be greatly appreciated.
You need to keep a reference to each instance of each form if you want to access the public properties of the instantiated form.
One way is to have a class with a static variable for each type of form:
class FormReferenceHolder
{
public static Form1 form1;
public static Form2 form2;
}
This way you would set the static variable whenever you instantiate a form, and then you can access that variable from anywhere in the program. You can go one step further with this and use properties that set up the form if it doesn't already exist:
class FormReferenceHolder
{
private static Form1 form1;
public static Form1 Form1
{
get
{
if (form1 == null) form1 = new Form1();
return form1 ;
}
}
}
...
static void Main()
{
Application.Run(FormReferenceHolder.Form1 );
}
I think I answered a previous question about this, which looks like it is what got you started down this route. The first point is that I wasn't recommending this pattern specifically, just trying to teach you more about how software developers can manage scope.
That said, the problem you are facing isn't insurmountable. You could hobble a public constructor by throwing an exception at runtime and not at design time, for instance, and modify Program.cs to use the static Instance instead of manually constructing the form.
But.
As I said in the other question, the better option would be to change architecture so that you don't need your library code to directly manipulate the GUI in the first place.
You can do this either by just having the GUI ask the library questions when it thinks it needs new data (simple functions) or by letting the GUI be notified when something needs to change. Either method would be better than having the library fiddle with labels directly.
A good place to start would be something like an MVC (model-view-controller) architecture, which I was alluding to in my previous answer. It might be best, though, to give us an idea of what your high-level program structure looks like now on a bit more detail. What are the main classes you are using in your system (not just the ones you've mentioned so far)? What is the main responsibility of each, and where does each live? Then our recommendations could be a little more specific.
EDIT
So, I have mocked up a quick demo of a possible alternative architecture, based on your comment.
I have the following in my project:
FormMain (Form)
TitleScreen (UserControl)
InGameMenu (UserControl)
MainScreen (UserControl)
GameController (Class)
GameModel (Class)
I didn't use Date and LoadSave, for now.
FormMain simply has an instance of each UserControl dropped on it. No special code.
GameController is a singleton (since you tried to use this pattern already and I think it would be helpful for you to try using a working version of it) that responds to user input by manipulating the model. Note well: you don't manipulate the model directly from your GUI (which is the View part of model-view-controller). It exposes an instance of GameModel and has a bunch of methods that let you perform game actions like loading/saving, ending a turn, etc.
GameModel is where all your game state is stored. In this case, that's just a Date and a turn counter (as if this were going to be a turn-based game). The date is a string (in my game world, dates are presented in the format "Eschaton 23, 3834.4"), and each turn is a day.
TitleScreen and InGameMenu each just have one button, for clarity. In theory (not implementation), TitleScreen lets you start a new game and InGameMenu lets you load an existing one.
So with the introductions out of the way, here's the code.
GameModel:
public class GameModel
{
string displayDate = "Eschaton 23, 3834.4 (default value for illustration, never actually used)";
public GameModel()
{
// Initialize to 0 and then increment immediately. This is a hack to start on turn 1 and to have the game
// date be initialized to day 1.
incrementableDayNumber = 0;
IncrementDate();
}
public void PretendToLoadAGame(string gameDate)
{
DisplayDate = gameDate;
incrementableDayNumber = 1;
}
public string DisplayDate
{
get { return displayDate; }
set
{
// set the internal value
displayDate = value;
// notify the View of the change in Date
if (DateChanged != null)
DateChanged(this, EventArgs.Empty);
}
}
public event EventHandler DateChanged;
// use similar techniques to handle other properties, like
int incrementableDayNumber;
public void IncrementDate()
{
incrementableDayNumber++;
DisplayDate = "Eschaton " + incrementableDayNumber + ", 9994.9 (from turn end)";
}
}
Things to note: your model has an event (in this case, just one of type EventHandler; you could create more expressive types of events later, but let's start simple) called DateChanged. This will be fired whenever DisplayDate changes. You can see how that happens when you look at the property definition: the set accessor (which you will NOT call from your GUI) raises the event if anyone is listening. There are also internal fields to store game state and methods which GameController (not your GUI) will call as required.
GameController looks like this:
public class GameController
{
private static GameController instance;
public static GameController Instance
{
get
{
if (instance == null)
instance = new GameController();
return instance;
}
}
private GameController()
{
Model = new GameModel();
}
public void LoadSavedGame(string file)
{
// set all the state as saved from file. Since this could involve initialization
// code that could be shared with LoadNewGame, for instance, you could move this logic
// to a method on the model. Lots of options, as usual in software development.
Model.PretendToLoadAGame("Eschaton 93, 9776.9 (Debug: LoadSavedGame)");
}
public void LoadNewGame()
{
Model.PretendToLoadAGame("Eschaton 12, 9772.3 (Debug: LoadNewGame)");
}
public void SaveGame()
{
// to do
}
// Increment the date
public void EndTurn()
{
Model.IncrementDate();
}
public GameModel Model
{
get;
private set;
}
}
At the top you see the singleton implementation. Then comes the constructor, which makes sure there's always a model around, and methods to load and save games. (In this case I don't change the instance of GameModel even when a new game is loaded. The reason is that GameModel has events and I don't want listeners to have to unwire and rewire them in this simple sample code. You can decide how you want to approach this on your own.) Notice that these methods basically implement all the high-level actions your GUI might need to perform on the game state: load or save a game, end a turn, etc.
Now the rest is easy.
TitleScreen:
public partial class TitleScreen : UserControl
{
public TitleScreen()
{
InitializeComponent();
}
private void btnLoadNew(object sender, EventArgs e)
{
GameController.Instance.LoadNewGame();
}
}
InGameMenu:
public partial class InGameMenu : UserControl
{
public InGameMenu()
{
InitializeComponent();
}
private void btnLoadSaved_Click(object sender, EventArgs e)
{
GameController.Instance.LoadSavedGame("test");
}
}
Notice how these two do nothing but call methods on the Controller. Easy.
public partial class MainScreen : UserControl
{
public MainScreen()
{
InitializeComponent();
GameController.Instance.Model.DateChanged += Model_DateChanged;
lblDate.Text = GameController.Instance.Model.DisplayDate;
}
void Model_DateChanged(object sender, EventArgs e)
{
lblDate.Text = GameController.Instance.Model.DisplayDate;
}
void Instance_CurrentGameChanged(object sender, EventArgs e)
{
throw new NotImplementedException();
}
private void btnEndTurn_Click(object sender, EventArgs e)
{
GameController.Instance.EndTurn();
}
}
This is a little more involved, but not very. The key is, it wires up the DateChanged event on the model. This way it can be notified when the date is incremented. I also implemented another game function (end turn) in a button here.
If you duplicate this and run it, you'll find that the game date is manipulated from lots of places, and the label is always updated properly. Best of all, your controller and model don't actually know anything at all about the View-- not even that it's based on WinForms. You could as easily use those two classes in a Windows Phone or Mono context as anything else.
Does this clarify some of the architecture principles I and others have been trying to explain?
In essence the problem is that when the application runs, it's going to try to instantiate the main form-window. But by using the Singleton pattern, you're essentially forbidding the application from doing that.
Take a look at the sample code here:
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.aspx
You'll notice in particular this section:
[STAThread]
public static void Main()
{
// Start the application.
Application.Run(new Form1());
}
Notice how the program is trying to instantiate Form1. Your code says, nah, I don't really want that since you mark the constructor as private (same holds true for static forms as well). But that's counter to how windows forms is supposed to work. If you want a singleton form-window, just don't make any more. Simple as that.

Updating text box from another class

I'm trying to update a text box from a class called 'hex' to the main form. Within the class 'hex' I have the following code:
Main m = new Main();
m.updateTextBox(convertedHex);
the code passed the variable to the main form to the method called 'updateTextBox' as shown below:
public void updateLog(string input)
{
textBox2.AppendText(input);
}
Sorry if this seems like a silly questions I have been stuck for a while, all the links on my google searches are now purple so I was hoping if someone could explain this to me. Many thanks.
Add this kind of method inside your Main class where textBox is created and call it from outside.
Lets say you added the code in your Program.cs class to start new
// Add this code in Program.cs (or similar where you start the gui
public static readonly Main MainLogWindow = new Main();
// Add this code in Main.cs class
private delegate void NameCallBack(string varText);
public void UpdateTextBox(string input) {
if (InvokeRequired) {
textBox.BeginInvoke(new NameCallBack(UpdateTextBox), new object[] {input});
} else {
textBox.Text = input;
// textBox.Text = textBox.Text + Environment.NewLine + input // This might work as append in next line but haven't tested so not sure
}
}
Call it like: Program.MainLogWindow.UpdateTextBox("test test"); from anywhere assuming that you have MainLogWindow open
This will also allow you to call updates from within other threads.
You have not given us very much information to go on. But as I said in my comment if your startup form is Main, the code that you are showing is creating a new Main Form and any changes made to it will not appear in your UI. You need to pass the form instance to the Hex class constructor. I would do something like this(assuming that the namespaces are the same, they are on the same thread, and your Hex Class is not Static. if on different threads you need to use the Method shown by MadBoy)
public partial class Form1 : Form
{
Hex hex;
public Form1()
{
InitializeComponent();
hex = new Hex(this);
}
}
class Hex
{
Form1 m;
public Hex( Form1 frm)
{
m = frm;
m.updateTextBox("Hello World");
}
}
Your class, presumably a business object, generally shouldn't be concerned with updating the UI. It doesn't particularly need to know that you even have a UI. But there are a couple of different useful approaches you could use.
1) Simply have your UI invoke your business object's method, and let the method return a value, and then the UI can choose to display it.
// inside Main form
var hex = new Hex();
string convertedHex = hex.GetConvertedHex(someArgument);
UpdateTextBox(convertedHex);
2) Have your business object expose an event. The arguments for the event would include whatever string that needs to be broadcast to whomever subscribes to the event. The UI would then be one of the subscribers.
Of the two ideas, I would generally opt for the first unless you actually do need an event model.
jest simple no need to do all of this make text box public from the properties and pass the current form object to the class throudh a method like this
public void mthod(){
//crete a obj of the class
cls1 obj=new clas1();
obj.smethod(this);
}
now in the class can cal it like this
smethod(from1 obj){
obj.textbox.text="";
}

Categories

Resources