Change a form label text value when setting a static int - c#

I'm trying to change a form label's text value (frmWebInput.ConnectedUserCount.Text) when changing a static int value from another static void...
Basically: It's a simple web server, and I'm trying to keep track of the connected users when each page is served. It seems to be working, but the form label is not getting changed though?
/**
* #type int Total connected users.
*/
private static int _connectedUsers = 0;
public static int connectedUsers {
get { return _connectedUsers; }
set
{
_connectedUsers = value;
frmWebInput MyForm = new frmWebInput();
MyForm.ConnectedUserCount.Text = String.Format("Connected Users: {0}", value);
}
}
public static void clientListener()
{
while (true)
{
try
{
HttpListenerContext request = listener.GetContext();
ThreadPool.QueueUserWorkItem(processRequest, request);
}
catch (Exception e) { }
}
}
public static void processRequest(object listenerContext)
{
try
{
connectedUsers = connectedUsers + 1;
}
}

Is this a WinForms application running on the web server? Or is this a WebForm?
In any event, you never show the form:
frmWebInput MyForm = new frmWebInput();
MyForm.ConnectedUserCount.Text = String.Format("Connected Users: {0}", value);
Every time the value is set, you create a new instance of frmWebInput and set the text on that instance. But you never show it. If one is already shown elsewhere in the application, you never set its text.
You need a reference to the instance of the form being shown. Something like:
private static frmWebInput MyForm { get; set; }
private static int _connectedUsers = 0;
public static int connectedUsers {
get { return _connectedUsers; }
set
{
_connectedUsers = value;
MyForm.ConnectedUserCount.Text = String.Format("Connected Users: {0}", value);
}
}
And, of course, that reference would have to be set with the instance of the form. Since it's static it would have to be within the static initializer. Either that or instead of an auto-implemented property it can just be a get which dynamically fetches the instance of the form. It's difficult to advise on the best approach since I don't know how this code interacts with the form instance.

Related

How do you make a form identifier equal to the value of a string variable in C#?

So , I have a function called CreateWindow(string id,int width,int height,string title);
as you might have guessed, this function creates a window whenever called and adds the parameters. I plan to do it like this:
public static void CreateWindow(string id,int width,int height,string title) {
Form (value of id) = new Form();
(value of id).Text = title;
(value of id).Size = new Size(width,height);
Main(Form (value of id));
}
But, I need to make the identifier of the form equal to the variable 'id' or I won't be able to get anything done, I can't just replace (value of id)with , for instance form1because if the user wants to change another property of the window he should be able to simply do, for instance: (value of id).BackColor = Color.Green;
I've added a complete program for you to try below, without any error handling to keep it short. Just create a new windows application and paste the code in.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace CreateFormWindowSO
{
static class Program
{
[STAThread]
static void Main()
{
var windowId = "Some window";
CreateWindow(windowId, 320, 240, "My Window");
// Put a breakpoint on the line below and step over it with the debugger.
// You'll see it returns the correct form object that was created above.
var someWindow = GetWindow(windowId);
// Do something with 'someWindow'.
}
static Form GetWindow(string id)
{
return windows[id];
}
static void CreateWindow(string id, int width, int height, string title)
{
Form form = new Form();
form.Text = title;
form.Size = new Size(width, height);
windows.Add(id, form);
}
static Dictionary<string, Form> windows = new Dictionary<string, Form>();
}
}
The idea behind the dictionary is you're now able to associate a Form with a particular 'key' (i.e. id in this case). That enables you to look up a particular window by supplying GetWindow() with a key that you presumably keep track of elsewhere. You can now create windows separately, and fetch them at any point later on whenever you need them.
I don't think that dynamic variable naming is possible. You could have a static dictionary of forms such as public static Dictionary<string, Form> forms; and add your new forms to the collection using the id for the index.
public static Dictionary<string, Form> forms = new Dictionary<string, Form>();
public static Form CreateWindow(string id, int width, int height, string title)
{
if (!forms.ContainsKey(id))
forms.Add(id, new Form());
forms[id].Text = title;
forms[id].Width = width;
forms[id].Height = height;
return forms[id];
}

Pass Values from Form -> Class -> Form C#

I have 2 Forms: V.Batch and V.BatchEdit and a Class: M.Batch
In V.Batch there is a DataGrid. I want to pass the value I get from the DataGrid to V.BatchEdit and the get set method is in M.Batch.
The problem here is that the value isn't passed properly in V.BatchEdit. It returns 0.
Here is the code
V.Batch:
M.Batch bt;
public Batch()
{
bt = new M.Batch();
InitializeComponent();
}
private void metroButton3_Click_1(object sender, EventArgs e)
{
bt.batchNum = Convert.ToInt32((metroGrid2.CurrentCell.Value).ToString());
V.BatchEdit bEdit = new V.BatchEdit();
this.Hide();
bEdit.Show();
}
M.Batch:
public int batchNum;
public int BatchNum
{
set { batchNum = value; }
get { return batchNum; }
}
V.BatchEdit
static M.Batch bt = new M.Batch();
DataSet a = bt.getBatch(bt.batchNum);
public BatchEdit()
{
db = new Database();
InitializeComponent();
System.Windows.Forms.MessageBox.Show(bt.batchNum.ToString() + "Batchedit");
try
{
metroTextBox1.Text = a.Tables[0].Rows[0][2].ToString();
}
catch (Exception exceptionObj)
{
MessageBox.Show(exceptionObj.Message.ToString());
}
}
I'm new to coding and c#. I'm not sure if I placed static even though it should not be static or what.
Yes, you are using static improperly here.
The easiest way to see what's going wrong is to notice that you are calling new M.Batch() twice. That means you have two different instances of M.Batch in your application. And nowhere in your code do you attempt to share those instances.
What you should be doing is passing your instance of M.Batch from one form to another, e.g. in the constructor:
// V.Batch
bt.batchNum = Convert.ToInt32((metroGrid2.CurrentCell.Value).ToString());
V.BatchEdit bEdit = new V.BatchEdit(bt);
this.Hide();
bEdit.Show();
// V.BatchEdit
private M.Batch bt;
private DataSet a;
public BatchEdit(M.Batch batch)
{
this.bt = batch;
this.a = this.bt.getBatch(bt.batchNum)
// Rest of your code here.
}
If You don't need the 'M.Batch' class for something else and you only use it for passing the value to V.BaychEdit, just declare a public property in V.BatchEdit like you did in M.Batch and use it like this:
V.BatchEdit bEdit = new V.BatchEdit();
bEdit.BatchNum = Convert.ToInt32((metroGrid2.CurrentCell.Value).ToString());
Your problem is that although your using statics you're still assigning a new instance to the static field.

WPF databinding during using the Arduino

I am developing a application with C# and Arduino.I reading values from Arduino and set the value on the textbox.I want always read value from Arduino and set this on the interface.However this code doesn't working.
Shoul I run while statement in a different thread?
This is my code
SerialPort port = new SerialPort("COM4", 9600);
port.Open();
while (true)
{
String s=port.ReadLine();
txtValue.Text=s;
}
port.Close();
}
I want show value which I read from Arduino to show in the textbox simultaneously.
This is code to start (put it in constructor, window Loaded or button click event):
Task.Run(() =>
{
_stop = false; // define as private field of window class
var port = new SerialPort("COM4", 9600);
port.Open();
while (!_stop)
{
var s=port.ReadLine();
Dispatcher.Invoke(() => txtValue.Text = s); // InvokeAsync?
}
port.Close();
});
This is code to stop (put it into window Closing event):
_stop = true;
This doesn't uses any bindings, but should give you an idea of how to organize port operation (with or without bindings).
I can't speak to the arduino side, but if you are using .net 4.0 or 4.5 you could do something like below:
Task myTask = Task.Factory.StartNew(() => {
while (true)
{
String s=port.ReadLine();
txtValue.Text=s;
}
});
as mentioned by Sinatr be sure to have a way to stop execution. You could do this by setting a vairable instead of using "true". As for where to put the code it is really dependent on what your final program will be.
With MVVM Light and SolidSoils4Arduino you should be able to quickly create an observable binding with Arduino serial messages.
Here is a basic viewmodel class:
public class MainViewModel : GalaSoft.MvvmLight.ViewModelBase, IObserver<string>
{
#region Fields
private string _lastSerialMessageReceived;
private readonly ObservableCollection<string> _serialMessages = new ObservableCollection<string>();
#endregion
#region Constructors
public MainViewModel()
{
var connection = new Solid.Arduino.SerialConnection("COM3", Solid.Arduino.SerialBaudRate.Bps_115200);
var session = new Solid.Arduino.ArduinoSession(connection);
session.CreateReceivedStringMonitor().Subscribe(this);
}
#endregion
#region Public Interface
public void OnCompleted()
{
throw new NotImplementedException();
}
public void OnError(Exception error)
{
throw new NotImplementedException();
}
public void OnNext(string value)
{
_serialMessages.Add(value);
LastSerialMessageReceived = value;
}
public ObservableCollection<string> SerialMessages
{
get { return _serialMessages; }
}
public string LastSerialMessageReceived
{
get { return _lastSerialMessageReceived; }
private set { Set(() => LastSerialMessageReceived, ref _lastSerialMessageReceived, value); }
}
#endregion
}
You can bind your textbox to property LastSerialMessageReceived. Property SerialMessages could be bound to a listbox.

global "class object" or global "server object"

I am doing a project including a custom OPC Client.
The Class Main represents the MainWindow in a WPF application.
The private field _opcServer will hold an object for further use.
Only one _opcServer object is allowed at any time.
I came up with this (it's all sample code and works fine)
// "Main" Class --> it's a WPF Window
public class Main
{
// the "global" server object
private OpcServer _opcServer = new OpcServer();
public Main() {}
private void connectOpcServer()
{
if(this._opcServer == null)
{
// the "global" server object
this._opcServer = this.opcClientFactory().connectOpcServer("someOpcServer");
if(this._opcServer != null)
{
// we made the connection
}
else
{
// connection failed
}
}
}
private void disconnectOpcServer()
{
if(this._opcServer != null)
{
if(this.opcClientFactory().disconnectOpcServer(this._opcServer))
{
// disconnected
this._opcServer = null;
}
else
{
// something went wrong
}
}
}
private OpcClient ocpClientFactory()
{
OpcClient opcClient = new opcClient();
return opcClient;
}
}
// Client Class
public class OpcClient
{
// the server object
private OpcServer _opcServer = new OpcServer();
public OpcClient() {}
public OpcServer connectOpcServer(string progID)
{
bool madeConnection = this._opcServer.Connect(progID);
if(madeConnection)
{
return this._opcServer;
}
else
{
return null;
}
}
public bool disconnectOpcServer(OpcServer opcServer)
{
this._opcServer = opcServer;
if(this._opcServer.disconnect())
{
this._opcServer = null;
return true;
}
return false;
}
}
Not much comments in the code but I think you get the point.
Every time connect or disconnect is triggered via user action, a new object of the OPC Client is created and the Server Object is passed in the one or the other direction.
There will be more methods (like read tags, etc ...) like this, but since the user should use them only once or twice per day, I see no problem with creating new objects and passing something between them.
But what if there is a real funny user who thinks he has to use these things (connect/disconnect/ etc...) all the time. Then I will end up creating many objects!
I gave it a thought and came up with this.
public class Main
{
// the client object
private OpcClient _opcClient = OpcClient.Instance;
public Main(){}
private void connectOpcServer()
{
if(this._opcClient.connectOpcServer("someOpcServer"))
{
// we made the connection and can now use
// this._opcClient.opcServer
}
else
{
// connection failed
}
}
private void disconnectOpcServer()
{
if(this._opcClient.disconnect())
{
// disconnected
}
else
{
// something went wrong
}
}
}
public class OpcClient
{
private static OpcClient _instance;
public static OpcClient Instance
{
get
{
if(instance == null)
{
_instance = new OpcClient();
}
return _instance;
}
}
private OpcClient()
{
this.opcServer = new OpcServer();
}
public OpcServer opcServer
{
get;
private set;
}
public bool connectOpcServer(string progID)
{
return this.opcServer.Connect(progID);
}
public bool disconnectOpcServer()
{
return this.opcServer.disconnect();
}
}
Now I create a singelton of the OPC Client and pass it to the main class. Now only one object will be created, the user can click connect/disconnect all day long.
What is the best way to proceed here?
Store the Server Object in the main class
Store the Class Object in the main class
Depends
Both are bad ideas (if so, why? What can I do instead?)
I am choosing the 2nd option.
By choosing the singleton approach I can make sure that there is only one Server Object.
This is very important.

Get/Set error "An object reference is required for the non-static field ...."

I get an error message "An object reference is required for the non-static field, method, or property...." for calling Refresh function :
// Status
public static string Status
{
get
{
return status;
}
set
{
status = value;
Refresh();
}
}
private void Refresh()
{
lblStatus.Text = Status.ToString();
}
Simply make the Status property non-static. Clearly you do not share this property across all the instances of that class. It looks like you are working with a control or a page class and you trying to call other instance methods or properties also.
So this will fix the compilation error.
public string Status
....
You can only call static functions from static functions.
It should be like
public static string Status
{
get
{
return status;
}
set
{
status = value;
Refresh();
}
}
private static void Refresh() // Change signature of function
{
lblStatus.Text = Status.ToString();
}
OR
Make property Non-static
public string Status // Change signature of property
{
get
{
return status;
}
set
{
status = value;
Refresh();
}
}
private void Refresh()
{
lblStatus.Text = Status.ToString();
}
I think this is a bad design, because lblStatus is a control, I guess, so it cannot be static, so the Refresh cannot be static.
Therefore, you should not call Refresh() in a static context anyway...
This is a bad design. You should remove the static from the Status.
What you are trying to do is to set instance value from static Property.
You can only modify static fields/properties from static properties/methods.
If you are insisting that Status must be Static then you have to create another static property/field and update through this field. (THIS IS HOWEVER VERY BAD).
Example:
Assuming Status is defined in class Form1, and there will be only one Form1 Instance
Class Form1
{
private static Form1 staticInstance = default(Form1);
Form1()
{
staticInstance = this;
}
public static string Status
{
get
{
return status;
}
set
{
status = value;
Refresh();
}
}
private static void Refresh() // Change signature of function
{
if(staticInstance != default(Form1)
staticInstance .lblStatus.Text = Status.ToString();
}
}

Categories