Subscribe to event in dll from another application - c#

I've been looking all over for a possible solution, but none seem to come close to what I actually need. I have a windows form which outputs to a class library (dll). I reference this dll into a console application and then launch the GUI in the dll. I want to be able to subscribe to a control event and do what ever code in my console application.
I have no problem when I want to read or write properties in the dll directly from my console app. Example:
MyDll.MyClass myObj = new MyDll.MyClass();
myObj.Textbox1.Text = "Hello World!";
However, I would like to subscribe to the TextChanged event in my dll and output the new text to my console app. Something along the lines of:
public void textbox1_TextChaned(object sender, EventArgs e)
{
Console.WriteLine(myObj.textbox1.Text);
}
Is there any way to subscribe directly to that event? or some other event?

Set the modifier of textbox1 to public
Subscribe to the TextChanged event:
myObj.Textbox1.TextChanged += textbox1_TextChaned;
The following code in a console app works for me. I'm referencing a Windows Form Application rather than a DLL, but I don't think there should be much difference:
class Program
{
static WindowsFormsApplication1.Form1 frm;
static void Main(string[] args)
{
frm = new WindowsFormsApplication1.Form1();
frm.textBox1.TextChanged += textBox1_TextChanged;
System.Windows.Forms.Application.Run(frm);
}
static void textBox1_TextChanged(object sender, EventArgs e)
{
Console.WriteLine((frm.textBox1.Text));
}
}

This doesn't answer your question directly, but it will solve your problem in a neater way, IMO.
In your DLL define an interface (IEventProcessor).
In your console
application implement the interface (ConsoleEventProcessor).
Pass an instance through the constructor of the form
call its methods from the events in the form.
In the console app:
IEventProcessor processor = new ConsoleEventProcessor();
MyDll.MyClass myObj = new MyDll.MyClass(processor);
Then in the form:
IEventProcessor _processor;
// constructor
public MyClass(IEventProcessor processor)
{
_processor = processor;
}
public void textbox1_TextChaned(object sender, EventArgs e)
{
// pass whatever parameters you need to use in the method
_processor.ProcessText1Changed(textbox1.Text);
}

Related

Trying to make the method of a button click use variable in WPF

I am new to WPF and Coding in general, I am trying to create a small UI to read and write data on .txt files. All the reading part functions works well but now I am having trouble making a small UI to display the information found in the .txt files.
My problem is more with how button clicks work in WPF. All the data is stored in the forms of object of class Static_Data_Scheme and Dynamic_Data_Scheme inside the program, these class are just simple collection of Dictionaries Objects. Part of my data is 'static' meaning it will be stored in .txt files that won't change location and so can be loaded when the program is started, and another part of my data is 'Dynamic' meaning it can be stored anywhere and the file path can be changed using a file explorer in the program. Important thing to note, the Static_Data_Scheme is needed to generate the Dynamic_Data_Scheme.
My initial way of handling it when I made the program to test it out was to generates both Data Scheme with the same button press called load, but since the static dictionaries can be loaded right at the start of the program I want to try and add that method to the MainWindow instead and only have the program generates the Dynamic_Data_Scheme when I press the load button, but I'm unable to find any documentation on how to add arguments to the click method of the button.
Current code that works but that I don't like due to the fact that Static_Data_Scheme.Start method is called each time the load button is pressed and could instead be loaded only once when the program starts :
public MainWindow()
{
InitializeComponent();
}
private void Save_Loader_Click(object sender, RoutedEventArgs e)
{
Static_Data_Scheme static_Data_Scheme = new Static_Data_Scheme();
static_Data_Scheme = static_Data_Scheme.Start();
Dynamic_Data_Scheme dynamic_Data_Scheme = new Dynamic_Data_Scheme();
Save_Parser.Parse_Save(#"file_path", static_Data_Scheme, ref dynamic_Data_Scheme);
}
What I wanna try to achieve is something like that :
public MainWindow()
{
InitializeComponent();
Static_Data_Scheme static_Data_Scheme = new Static_Data_Scheme();
static_Data_Scheme = static_Data_Scheme.Start();
}
private void Save_Loader_Click(object sender, RoutedEventArgs e)
{
Dynamic_Data_Scheme dynamic_Data_Scheme = new Dynamic_Data_Scheme();
Save_Parser.Parse_Save(#"file_path", static_Data_Scheme, ref dynamic_Data_Scheme);
}
But this doesn't work due to the fact that the Save_Parser.Parse_Save method lack the static_Data_Scheme variable and I can't add it to the Save_Loader_Click method either.
So my question is how do I tell my ave_Loader_Click method to get the static_Data_Scheme from the program?
You almost had it, just move the variable outside of your method:
Static_Data_Scheme static_Data_Scheme = new();
public MainWindow()
{
InitializeComponent();
/* static_Data_Scheme = ???? */static_Data_Scheme.Start();
}
private void Save_Loader_Click(object sender, RoutedEventArgs e)
{
var Data_Scheme = new Dynamic_Data_Scheme();
Save_Parser.Parse_Save(#"file_path", static_Data_Scheme, ref dynamic_Data_Scheme);
}

Cross-class communication

I'm running a main WinForm with most UI elements, and then an Add form is called when the Add button is picked. It should receive input, and send it back to the WinForm once accepted.
This code runs when you click the "Add" button on the main class:
public void addButton_Click(object sender, EventArgs e)
{
AddView newadd = new AddView();
newadd.Show();
}
This code (also in the main class) should run based upon a button in the AddView:
public void AddDashObject(string dashName, string dashIdentifier, int dashFunction, string dashFunctionInfo, int dashVerbosity)
{
DashObject tmp = new DashObject("","",0,"",0);
tmp.DashName = dashName;
tmp.DashIdentifier = dashIdentifier;
tmp.DashFunction = dashFunction;
tmp.DashFunctionInfo = dashFunctionInfo;
tmp.DashVerbosity = dashVerbosity;
dashloaded.Add(tmp);
ReloadDashObjects();
}
I'm not really sure how to communicate between the forms - I can use a type created in the main class, and also methods, but I'm pretty sure I'm creating a separate instance. How can I communicate with the existing one?
MainView mnfrm = new MainView();
MainView.DashObject tmp = new MainView.DashObject("","",0,"",1); // Defaults
private void button1_Click(object sender, EventArgs e)
{
mnfrm.dashloaded.Add(tmp); // Add the default DashObject to MainView's currently loaded DashObjects
mnfrm.ReloadDashObjects(); // Reload the list
}
Not sure how to proceed on this - any advice?
Since the Add dialog is expected to be modal, the decoupled way to do this is to only close the dialog with an OK status. I.e. the form is just an input control that doesn't actually "do" anything.
Then the main form can:
1) check how the dialog was closed right after ShowDialog(),
2) call some GetResult() function to get the values from the add form before disposing it.
3) call the business logic that actually creates and reloads the DashObjects.

C# - dll event handler

I am setting a .dll file to create a new form and a new button, but i want that button to do something. Is it possible to create a event handler in a dll file?
public static byte sbuton( string er, int by,int re)
{
Form fg = new Form();
fg.Show();
Button b1 = new Button();
fg.Controls.Add(b1);
b1.Text = er;
b1.Location = new Point(by, re);
return 0;
}
This is the code that creates a form with a button in it.
When I try to create a new event handler, as I would in a form, I get this error: "An object reference is required for the non-static field, method or property".
public static byte sbuton( string er, int by,int re)
{
Form fg = new Form();
fg.Show();
Button b1 = new Button();
fg.Controls.Add(b1);
b1.Text = er;
b1.Location = new Point(by, re);
b1.Click += new EventHandler(b1_click);
}
private void b1_click(object sender , EventArgs e)
{
}
This is the code from the form where I want use the dll
private void button1_Click(object sender, EventArgs e)
{
if (richTextBox1.Text.Contains("add") && richTextBox1.Text.Contains("buton") && richTextBox1.Text.Contains("text"))
{
form.sbuton("buton", 10, 10);
}
}
This creates a button, but nothing happens when the button is clicked, because no event handler is assigned to it in the .dll file.
And also,sorry for the bad english,it is not my native language.
What can i do?
Thanks!
It's not clear from your question what the context is. Without a good, minimal, complete code example it's difficult to provide a really good answer.
But in your example, it appears that your event handler is in the same DLL (and I assume, the same class) as the sbuton() method. If that's the case, then all you need to do in order to use the event handler is make it a static method:
private static void b1_click(object sender , EventArgs e)
{
}
Now, since you didn't post any of the code in the method, never mind the full context, it's not certain that would work. I.e. if there is a good reason for that method being a non-static method, then you will have to subscribe the event handler by referring to the method with a reference to an actual instance of the containing class. If that's the case, then the question commenter Daniel Kelley suggests, An object reference is required for the non-static field, method, or property?, may turn out to be appropriate for your needs after all.
Finally, note that none of this has anything to do with the code being in a DLL. You would have run into this same problem had your sbuton() method been in the same project from which you're calling it.

UI Forms events block my other STOCK TICKER API events - how can I prevent this?

I have an API (dll) that collects stock ticks via an event mechanism. Such as below:
...
using MT4API;
public partial class Blue : Form
{
...
public Blue()
{
...
string symbol = "GBPUSD";
MT4DDE dde = new MT4DDE("");
dde.OnQuote += new System.EventHandler<QuoteEventArgs>(MT_OnQuote);
dde.Connect();
dde.Subscribe(symbol);
....
The idea is that on each chart tick I get an event. here is the event handler code:
private static void MT_OnQuote(object sender, QuoteEventArgs args)
{
GlobalClass.Ask = args.Ask;
GlobalClass.Bid = args.Bid;
// I have back ground worker code that updatestables from the global class
}
This all works fine. So long as I do not touch any other buttons on the form UI. As soon as I click a button on the form of the UI... I no longer receive events from my API, the UI application functions normally, but with no data from the API.
Why do events from the UI stop any further events coming from the API event?
Any idea whats going on here? Or suggestions how to design this?
Does the same problem occur if you comment out your code that updates the tables from the global object? and if you comment out the background worker?
It would be a good idea to distinguish if the event stops being fired just after you press some button on the UI, or if it stops being fired only after some line of code you wrote is being executed.
In order to be able to help you, we would need to know how the event on the MT4DDE class is triggered.
If you have the code for this class, posting it would help.
If you don't you may want to use a tool such as Reflector to decompile the assembly into C# and see what the MT4DDE class is doing that might cause it to stop invoking the event.
In addition, if you are doing anything related to background threads, or if you're doing anything unusual with your application's main message loop, it would be a good idea to mention it here.
I have tried to use the invoke command, it works, but after a few events it stops...here is the code isolated:
using MT4API;
namespace WindowsFormsApplication1
{
public delegate void UpdateTextCallback(double ask, double bid);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
string symbol = "GBPUSD";
MT4DDE dde = new MT4DDE("");
dde.OnQuote += new EventHandler<QuoteEventArgs>(MT_OnQuote);
dde.Connect();
dde.Subscribe(symbol);
}
private void updateTickDisplay(double ask, double bid)
{
textBox1.Text = ask.ToString();
textBox2.Text = bid.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
private void MT_OnQuote(object sender, QuoteEventArgs args)
{
BeginInvoke(new UpdateTextCallback(this.updateTickDisplay),
new object[] { args.Ask, args.Bid });
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox3.Text = textBox1.Text;
}
}
}
The only difference from the real code is that I am using a data grid....as opposed to a text field. But it is clear that the UI blocks somehow the new events. It is strange that I get about 5 to 10 events and then it just stops. Strange. Any ideas on a differnet design?

How to start WPF based on Arguments

I'm currently developing an application that does some file manipulation and I want to be able to do the manipulation through the console or via an UI (I chose WPF).
I pretty much want to say: (psuedo)
if ( Environment.GetCommandLineArgs().Length > 0 )
{
//Do not Open WPF UI, Instead do manipulate based
//on the arguments passed in
}
else
{
//Open the WPF UI
}
I've read about a few different ways of starting the WPF Window/application programmatically like:
Application app = new Application ();
app.Run(new Window1());
But I'm not entirely sure I want to just plug this into a Console Application.
Does anyone have best practices or recommendations on how I can achieve this? The main processing functionality is in a Helper class I created. So basically I either want a static start method (like standard Console Application creates) or the UI to access the Helper class depending on the arguments passed in.
In Application class there is an event "StartUp" you can use it . It provide you the args you provide through command prompt. Here is an example from MSDN:
App.xaml
<Application x:Class="WpfApplication99.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="App_Startup">
</Application>
App.xaml.cs
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
// Application is running
// Process command line args
bool startMinimized = false;
for (int i = 0; i != e.Args.Length; ++i)
{
if (e.Args[i] == "/StartMinimized")
{
startMinimized = true;
}
}
// Create main application window, starting minimized if specified
MainWindow mainWindow = new MainWindow();
if (startMinimized)
{
mainWindow.WindowState = WindowState.Minimized;
}
mainWindow.Show();
}
}
I hope this will help.
There are 2 options to get the command line arguments
1) If you want to read the arguments OnStartup. This is good for global access of the args.
Override OnStartup in App.xaml.cs and look at the Args property of the StartupEventArgs class.
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
foreach (string arg in e.Args)
{
// TODO: whatever
}
base.OnStartup(e);
}
}
2) Another easy way is to read the arguments from the Environment Object.
Environment.GetCommandLineArgs();
This can be used from anywhere in the application like from the Form / Page also.
I Prefer override OnStartup because the Startup event is usually registered in "App.xaml" and I sometimes don't want to modify it. And OnStartup function can provide a way to do some preprocess before Startup event is invoked. This is why we can override OnStartup!

Categories

Resources