Changing values of struct in another class - c#

While using Winform, I had defined a struct in a main GUI class and change the value of struct in another class. So this is my Program.cs:
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new App());
}
}
public struct StructExample {
public string str1;
public string str2;
}
and the codes for main GUI looks like:
public partial class App : Form {
public StructExample Example = new StructExample();
public App() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
ButtonToClick.Click += (s, evt) => {
AnotherGUI setWindow = new AnotherGUI(Example);
setWindow.ShowDialog();
};
}
}
and the codes for AnotherGUI looks like:
public partial class AnotherGUI : Form {
public StructExample Example;
public SettingsGUI(StructExample Example) {
InitializeComponent();
this.Example = Example;
}
private void DoSomething() {
//Change values in Example
Close();
}
}
But I have a problem that after closing AnotherGUI, the values of Example wouldn't change. What should I do to change the values of Example in AnotherGUI to use in App?

Struct is a value type so you will need to explicitly pass by ref in case you need the receiving method to modify it.
class Program
{
static void Main(string[] args)
{
var example = new Example() { Name = "Name"};
Console.WriteLine(example.Name);
WrongStructModifier(example);
Console.WriteLine(example.Name);
CorrectStructModifier2(ref example);
Console.WriteLine(example.Name);
}
static void WrongStructModifier(Example example)
{
example.Name = "Modified Name";
}
static void CorrectStructModifier2(ref Example example)
{
example.Name = "Modified Name";
}
}
struct Example
{
public string Name;
}

Related

C# calling public fields from a public static class

I'm just learning C# after using VBA for many years, I'm not a professional and this is something I do in my leisure. I'm looking to replicate the logic of using a public variable that can be accessed from a method and incremented by one each time when clicking button cmdPublicVartest , Below is the code I have so far, but am getting the error
An object reference is required for the non-static field, method, or property, in the publicvar class, it looks because it's a static class, however if I remove it from a static class, I would have to call an instance of the class on the button cmdPublicVartest. Is there a way I can keep publicvar a static class, so I don't have to do an instance of the class on the button?
namespace testDB
{
public partial class Database : Form
{
public string publictest = "public test";
public int pUblicint = 0;
public static void PublicVar()
{
MessageBox.Show(publictest + pUblicint);
pUblicint++;
}
private void cmdPublicVartest_Click(object sender, EventArgs e)
{
testDB.Database.PublicVar();
}
}
}
You cannot access non-static fields from a static method because they belong to an instance of the class, and when calling a static method you do not have an instance.
You could either make the fields static like this
public partial class Database : Form
{
public static string publictest = "public test";
public static int pUblicint = 0;
public static void PublicVar()
{
MessageBox.Show(publictest + pUblicint);
pUblicint++;
}
private void cmdPublicVartest_Click(object sender, EventArgs e)
{
testDB.Database.PublicVar();
}
}
Or make the method non-static like this
public partial class Database : Form
{
public string publictest = "public test";
public int pUblicint = 0;
public void PublicVar()
{
MessageBox.Show(publictest + pUblicint);
pUblicint++;
}
private void cmdPublicVartest_Click(object sender, EventArgs e)
{
PublicVar();
}
}
Just revise your code to this:
namespace testDB
{
public partial class Database : Form
{
public string publictest = "public test";
public int pUblicint = 0;
public void PublicVar()
{
MessageBox.Show(publictest + pUblicint);
pUblicint++;
}
private void cmdPublicVartest_Click(object sender, EventArgs e)
{
PublicVar();
}
}
}
While PublicVar() is static, the fields it references (publictest, pUblicint) are not. You have to make them static as well or make PublicVar() not-static.

C# How to access method of a class from another class it instantiates?

I have 2 classes where 1 class is like the main class and I have a secondary class which is instantiated from the main class. How am I able to use the main class' method from the secondary class. Here's code to give an illustration of what I want.
public class MainClass
{
private SecondaryClass secondaryClass;
private int testValue;
public MainClass()
{
this.secondaryClass = new SecondaryClass();
testValue = 0;
}
public void updateTestValue (int val)
{
testValue = val;
}
}
public Class SecondaryClass : Form
{
public SecondaryClass()
{
}
private void button1_click(Object sender, EventArgs e)
{
// I want to be able to do this:
primaryClass.updateTestValue(100);
}
}
You can make classes communicate without having one derive from another.
public class MainClass
{
private SecondaryClass secondaryClass;
private int testValue;
public MainClass()
{
this.secondaryClass = new SecondaryClass(this.UpdateTestValue);
testValue = 0;
}
public void UpdateTestValue (int val)
{
testValue = val;
}
}
public class SecondaryClass : Form
{
private Action<int> UpdateValue { get; }
public SecondaryClass(Action<int> updateValue)
{
this.UpdateValue = updateValue;
}
private void button1_click(Object sender, EventArgs e)
{
this.UpdateTestValue(100);
}
}
In this organization, primary class is passing a delegate to its own instance-level method when it creates the secondary class. Secondary class calls that delegate when appropriate, without ever knowing what function that is.
This is the example of the callback pattern.
There are other variants of the same idea. For example, primary class could implement an interface which defines the UpdateValue method. Then, it passes this reference to every object which needs access to that method. Other objects, like an object of secondary class, would then simply call a method of that interface, once again not knowing that it is in fact the primary class they are referencing.
public interface IListener
{
void Update(int value);
}
public class MainClass : IListener
{
private SecondaryClass secondaryClass;
private int testValue;
public MainClass()
{
this.secondaryClass = new SecondaryClass(this);
testValue = 0;
}
public void Update(int val)
{
testValue = val;
}
}
public class SecondaryClass : Form
{
private IListener Listener { get; }
public SecondaryClass(IListener listener)
{
this.Listener = listener;
}
private void button1_click(Object sender, EventArgs e)
{
this.Listener.Update(100);
}
}
The price of this solution is one additional type in the system (interface IListener), and the benefit is that you can avoid working with delegate syntax. Delegates have a drawback that their arguments have no names, and therefore you can easily make a bug if you mix them up.
public class MainClass: Form
{
private int testValue;
public MainClass()
{
testValue = 0;
}
public void updateTestValue (int val)
{
testValue = val;
}
}
public class SecondaryClass : MainClass
{
public SecondaryClass()
{
}
private void button1_click(Object sender, EventArgs e)
{
// I want to be able to do this:
updateTestValue(100);
}
}
A class can only have one base class
What you could do is move the :Form base class up to the primary class and then from your secondary class have it's base class as Primary class and use the functions as follows.
public class PrimaryClass : Form
{
private int testValue;
public void PrimaryClassMethod()
{
Console.WriteLine("Method from Primary Class");
}
public void UpdateTestValue (int val)
{
testValue = val;
}
}
public class SecondaryClass : PrimaryClass
{
public void CallPrimaryClassMethod()
{
this.PrimaryClassMethod();
this.UpdateTestValue(10000);
}
}
https://dotnetfiddle.net/PC2WVu

How to update progress bar from another class C#?

I have my progressbar in form1. and i have another class called process.cs
In the main form I have these two functions...
public void SetProgressMax(int max)
{
uiProgressBar.Value = 0;
uiProgressBar.Minimum = 0;
uiProgressBar.Maximum = max;
}
public void IncrementProgress()
{
uiProgressBar.Increment(1);
}
How can I call these functions from my process.cs class?
You're creating a "tightly coupled" solution which requires the process class to have a reference to the Form (I'll use Form1 in this example).
So in your process class, you need to create a variable to store the reference to the form, and allow a way to pass that reference in. One way is to use the constructor of the class:
public class process
{
private Form1 f1 = null;
public process(Form1 f1)
{
this.f1 = f1;
}
public void Foo()
{
if (f1 != null && !f1.IsDisposed)
{
f1.SetProgressMax(10);
f1.IncrementProgress();
f1.IncrementProgress();
f1.IncrementProgress();
}
}
}
Here's an example of creating the process class from within Form1 and passing the reference in:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
process p = new process(this);
p.Foo();
}
public void SetProgressMax(int max)
{
uiProgressBar.Value = 0;
uiProgressBar.Minimum = 0;
uiProgressBar.Maximum = max;
}
public void IncrementProgress()
{
uiProgressBar.Increment(1);
}
}
--- EDIT ---
Here's a boiled down version of the "loosely coupled" events approach (ignoring multi-threading issues for simplicity):
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
process p = new process();
p.Progress += p_Progress;
p.Foo();
}
void p_Progress(int value)
{
uiProgressBar.Value = value;
}
}
public class process
{
public delegate void dlgProgress(int value);
public event dlgProgress Progress;
public void Foo()
{
// ... some code ...
// calcuate the current progress position somehow:
int i = (int)((double)3 / (double)10 * (double)100); // 30% complete
// raise the event if there are subscribers:
if (Progress != null)
{
Progress(i);
}
}
}
Note that in this approach the process class has no reference to the form and has no idea what is being done with the progress value. It simply reports the progress and the subscriber (the form in this case) decides what to do with that information.

Accessing GUI from another class via a static helper class

I just wanted to ask if the following code is a valid method to access the GUI from another class, or if it is bad practice. What I want to do is to write log messages into a RichTextBox in Form1.
If it's bad practice, would it be better to pass a reference of my Form1 to the other class to be able to access the RichTextBox.
I have the following code to access the GUI in my Form1 from another class:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Logger.Init(this.rtbLog);
MyOtherClass myOtherClass = new MyOtherClass();
myOtherClass.DoSomething();
}
}
public class MyOtherClass
{
public void DoSomething()
{
Logger.AppendText("text...");
Logger.AppendText("text...");
Logger.AppendText("text...");
}
}
public static class Logger
{
private static RichTextBox _rtb;
public static void Init(RichTextBox rtb)
{
_rtb = rtb;
}
public static void AppendText(String text)
{
_rtb.AppendText(text);
_rtb.AppendText(Environment.NewLine);
}
}
With Events (thanks to Ondrej):
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Logger.EntryWritten += Logger_EntryWritten;
MyOtherClass myOtherClass = new MyOtherClass();
myOtherClass.DoSomething();
}
void Logger_EntryWritten(object sender, LogEntryEventArgs args)
{
rtbLog.AppendText(args.Message);
rtbLog.AppendText(Environment.NewLine);
}
}
public class MyOtherClass
{
public void DoSomething()
{
Logger.AppendText("text...");
Logger.AppendText("text...");
Logger.AppendText("text...");
}
}
public static class Logger
{
public static event EventHandler<LogEntryEventArgs> EntryWritten;
public static void AppendText(string text)
{
var tmp = EntryWritten;
if (tmp != null)
tmp(null, new LogEntryEventArgs(text));
}
}
public class LogEntryEventArgs : EventArgs
{
private readonly String message;
public LogEntryEventArgs(String pMessage)
{
message = pMessage;
}
public String Message
{
get { return message; }
}
}
It's probably fine for a small throw-away project, but otherwise a logger should not know anything about used platform. Then it would be good to use events for example. Raise an event whenever there's a new log entry written and consumers interested in logged entries will subscribe to a delegate.
Also be careful with threads. If you log a message from a different thread than UI you will end up with an exception because you would access a GUI control from a different thread which is forbidden.
EDIT:
Something along these lines. LogEntryEventArgs is a type you have to create and you can give it properties like Message, TimeWritten, Severity, etc.
public static class Logger
{
public static event EventHandler<LogEntryEventArgs> EntryWritten;
public static void AppendText(string text)
{
var tmp = EntryWritten;
if (tmp != null)
tmp(null, new LogEntryEventArgs(text));
}
}
consumer:
Logger.EntryWritten += Logger_OnEntryWritten;
void Logger_OnEntryWritten(object sender, LogEntryEventArgs args)
{
_rtb.AppendText(args.Message);
_rtb.AppendText(Environment.NewLine);
}
Also, don't forget to invoke on a form/dispatch the body of Logger_OnEntryWritten in order to avoid cross-thread access exception (in case you are considering using threads).

C# Communication between plugin and host application

I am writing plugin based application.
Host application:
namespace CSK
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
LoadPlugins();
}
public void LoadPlugins()
{
DirectoryInfo di = new DirectoryInfo("./Plugins");
foreach (FileInfo fi in di.GetFiles("*_Plugin.dll"))
{
Assembly pluginAssembly = Assembly.LoadFrom(fi.FullName);
foreach (Type pluginType in pluginAssembly.GetExportedTypes())
{
if (pluginType.GetInterface(typeof(MainInterface.PluginHostInterface).Name) != null)
{
MainInterface.PluginHostInterface TypeLoadedFromPlugin = (MainInterface.PluginHostInterface)Activator.CreateInstance(pluginType);
MainInterface.IMother mother = new ApiMethods(this);
TypeLoadedFromPlugin.Initialize(mother);
}
}
}
}
}
Interface:
namespace MainInterface
{
public interface PluginHostInterface
{
void Initialize(IMother mother);
}
public interface IMother
{
MenuItem addMenuItem(String header, String name);
MenuItem addSubMenuItem(MenuItem menu, String header, String name);
Boolean receiveMessage(String message, String from);
Boolean addContact(String name, String status, String proto, String avatar = "av");
}
}
Test plugin:
namespace Plugin_Test
{
public class MainClass : MainInterface.PluginHostInterface
{
private MainInterface.IMother CSK;
public void Initialize(MainInterface.IMother mainAppHandler)
{
CSK = mainAppHandler;
}
}
}
And now, i want to execute some methods in Plugin Test from my host application. Of course, there will be many plugins, and not every of them will contain specified methods. I was trying to use events but with no success. Any idea how to do it?
Class with Events:
public class EventProvidingClass {
public event EventHandler SomeEvent;
public void InvokeSomeEvent() {
if(SomeEvent != null) SomeEvent.Invoke(this, new EventArgs());
}
}
Your Plugin Interface:
public interface PluginHostInterface
{
void Initialize(IMother mother);
void InitializeEvents(EventProvidingClass eventProvider);
}
Plugin Class:
public class MainClass : MainInterface.PluginHostInterface
{
private MainInterface.IMother CSK;
public void Initialize(MainInterface.IMother mainAppHandler)
{
CSK = mainAppHandler;
}
public void InitializeEvents(EventProvidingClass eventProvider)
{
eventProvider.SomeEvent += someEventHandler;
}
private void someEventHandler(object sender, EventArgs e)
{
}
}
and then call InitializeEvents after the Initialize function.
Of course you can put the events where you want them, you just need to make sure that you make them available for the Plugin so that the Plugin can assign its EventHandlers

Categories

Resources