Raising form event - c#

I have been finding that “Windows Forms App (.NET Core)” projects lack the functionality of normal “.NET framework” apps. I'm specifically using .NET Core 3.1.
I want to be able to raise a form event on an object, but cannot find a way to do this. In my example, I want to call click on a System.Windows.Forms.TextBox. I know calling TextBox.Focus() will essentially emulate the behavior, but that's not the point.
Calling an event handler for the forms apps object does not do the job either. It only calls my custom code, not the actual base event handlers. And Control.RaiseEvent does not exist in .NET core. I don't think Control.Invoke can do the job either, but I haven't tested.

The answer is that control events are callable through subclassed controls. For example
public class TestPictureBox : PictureBox
{
public void CallClick(EventArgs e = null) => base.OnClick(e ?? EventArgs.Empty);
public void CallResize(EventArgs e = null) => base.OnResize(e ?? EventArgs.Empty);
}
With these example functions you can raise the control’s events.

Related

Custom UserControl Won't show when fired by event in another project 'ClassLibrary'

I have two projects, one of them is my mainApplication and another is a classLibrary, where communicates with Hardware.
In the classLibrary I have an event, which is fired when x hardware is disconnected, on my mainApplication, I add that event to custom function, where
my custom control located on my mainApplication won't show up, but when call something like MessageBox, it shows ... Probably if I add that mainApplication to references on classLibrary it will work, but I don't want to do that.
Follow sample code
Class Library sat
public event ConnectedSATChanged connectionChanged;
MainApp
sat.connectionChanged += new
SAT.SATInternalFunctions.ConnectedSATChanged(Sat_connectionChanged);
private void Sat_connectionChanged()
{
MessageDialog.Show("WARNING"); // Wont show Or any other custom control
MessageBox.Show("Warning"); // Will Show ...
}
UPDATE
The follow code made it
var thread = new Thread(() =>
{
MessageDialog.Show("Warning!");
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Without adding reference you need to find a way to trigger an event in the class library. Either WCF, web server or database can be used here.

How can I wait Until a Form Handle Has Been Created Before Using Its' Components?

I am dynamically instantiating a Form. I cannot interact with the components (such as a TextBox) on the Form until the handle has been created (else, an exception will be thrown).
Currently I block the thread using a while loop:
public void OutputDesktopFrame(MessagingService service, DesktopFrame desktopFrame)
{
IRemoteDesktopView view = GetView(service);
view.UpdateFrame(desktopFrame);
}
private IRemoteDesktopView GetView(MessagingService service)
{
T view;
bool viewExists = _views.TryGetValue(service, out view);
if (viewExists == false)
{
view = CreateAndShowView(service);
}
return view;
}
private T CreateAndShowView(MessagingService service)
{
T remoteDesktopView = new T();
_views.Add(service, remoteDesktopView);
Thread pumpThread = new Thread(() => remoteDesktopView.ShowDialog());
pumpThread.Start();
while (remoteDesktopView.IsHandleCreated == false)
{
//Do not return until the handle has been created!
}
return remoteDesktopView;
}
I do not like this mechanism. I am looking for an elegant solution.
Please take into account that I am coding against an interface. I thought about using a ManualResetEvent or something of the like but having to implement and handle the ManualResetEvent within each Form that implements the interface doesn't sound appealing to me. If you don't agree with me. that's just fine. I merely suspect my current solutions are not the most elegant.
You can add code to a HandleCreated event handler like this:
private void Form1_HandleCreated(object sender, EventArgs e){
//your code
}
The event is not listed in Properties window, you have to register the event handler using code:
HandleCreated += Form1_HandleCreated;
You have to wait for the handle to be created somehow.
So you will end up with something like while (form.IsHandleCreated == false) { ... } somewhere in your code.
The only question is where to put it.
If you do it like in your example above, you need to code the while loop every time you create a form If you choose the alternative you mentioned, using an event raised by the form, you need to implement it in each form (and create an event handler and hook it up).
I don't know if CreateAndShowForm() is a framework method, or something you can change yourself. If you can change it, that's where I would put the waiting. That way you only need to code it once.
Another approach to avoid the code duplication would be handling it in the form, implementing it in your own abstract form base class, and deriving you actual forms from that class. In my opinion, that is complete overkill for this issue - way too much work for very little gain.
If you can't change CreateAndShowForm(), I recommend going with the example above - yes, it definitely isn't elegant, but it gets the work done, the source code is easy to understand, and it doesn't require the additional work of event handling.

Static event doesn't get subscribed in different dll

I have one WinForms control project that produces a dll. There is a second dll project (also winforms control) that uses the first project. There is a third winforms project, this time a form, that uses the second project. So [Third Project] <>------> [Second Project] <>--------> [First Project]
The first project exposes a static event. I'm trying to subscribe to that event from the third project. The event stays as null (not subscriptions) after the += call.
Why is it not subscribing? Is it because the Winforms controls have their own thread? The FirstProject user control is created on the fly at some point in time. But I will expect the static to work correctly, without doing anything else,
Project 1
namespace Something
{
public partial class FirstClass : UserControl
{
...
public delegate void EventHandler();
public static event EventHandler MyEvent;
...
}
}
Project 3
namespace Another
{
public partial class ThirdClass : Form
{
...
public ThirdClass()
{
....
Something.FirstClass.MyEvent += new Something.FirstClass.EventHandler(MyHandler);
}
public void MyHandler()
{
}
...
}
}
EDIT
I have created a small application with the basics to get the three projects and the static event. And it works. Therefore something else is going on.
EDIT 2
The dll that contained the first project, the one with the event, was being loaded twice. I have just added an alias, but didn't help. And still will not explain when just after the += the event is still null.
EDIT 3 I transformed the event so I have the add/remove accessors pair. It does enter into the add. The Handler method gets the value correctly (and therefore no null), but once it goes outside, is null again.
The static event should work just fine. Try to debug your code to make sure the event registration is being called and that the event itself gets fired as expected. The event does not care about threads. It will accept the registration either way. Threading will, however, cause an exception if you try to edit the form on a thread besides the UI thread.
And the reason will be in my EDIT 2. Because is a static event, loading twice the dll (two different paths) was creating two different static events (or two different handlers). My EDIT 3 clearly showed that the event was being subscribed to.
Once I forced the third project (the one subscribing to the static event) to load the dll from the same location as the project creating the event (I didn't wanted to use the GAC), all worked.

XAML C# Function across multiple windows

I've got a program I am working on that has multiple windows. The windows are similar in functionality and I want to have a single event handler to cover a button press event for each window in the application. Is this possible?
If you need to bind a handler in code behind you can encapsulate a handler by delegate and inject into the Windows which are required it.
For instance using Action<T>:
Action<string> commonHandler = (parameter) =>
{
// handler code here
};
class MyWindiow
{
public MyWindiow(Action<string> handler)
{
// store to local and assign to button click
// button.CLick += (o, e) => { handler(parameterToBepassed); }
}
}
I'd look into using a framework to help you out here. My favorite is Prism v4.
If you follow the M-V-VM design pattern you're life will be a lot easier. You'll need to understand Data Binding and DataContext.
That being said, if you decide to go this path, you can bind each of your windows to a command:
<Button Command="{Binding DoFooCommand}" Content="DoFoo"/>
You're ViewModel would have a DelegateCommand member to execute.
public class SomeViewModel : NotificationObject
{
public SomeViewModel()
{
DoFooCommand = new DelegateCommand(ExecuteFoo);
}
public DelegateCommand DoFooCommand { get; set; }
private void ExecuteFoo()
{
//Use the EventAggregator to publish a common event
}
}
And finally, somewhere else in your solution you'll have a code file/class that subscribes to the event and waits for someone to publish the event to process it.
public class SomeOtherPlace
{
public SomeOtherPlace()
{
//Use the EventAggregator to subscribe to the common event
}
public void FooBarMethodToCallWhenEventIsPublished(SomePayload payload)
{
//Do whatever you need to do here...
}
}
I realize some of the things were left out (such as what a "SomePayload" is... look into the EventAggregator information), but I did not want to get into it too much. Just give you a guide on where to go for information and some base code to work off of. If you decide to use the EventAggregator then you'll need to ensure that your subscribing call and publishing calls are utilizing the SAME instance of the EventAggregator. You can do this by looking into MEF. Prism is setup to work with MEF perfectly... I'm not going to lie. Doing all this requires a bit of a learning curve, but it will be worthwhile in the end when you can unit test your ViewModels easily and have your code loosely coupled. The EventAggregator is a great way for different classes to communicate to each other without relying on knowing about each other. And MEF is great for having a Container for your services that you want to utilize across your application.
Hope that gave you a bit of insight on how to go about doing what you want to do on the correct path.

Having problem in understanding and creating events in WPF

I am new to WPF, and I am learning using the book Pro WPF C# 2010.
Now in the chapter about events, the book explains how to create events and register events in WPF and it gives, as an example, code from the ButtonBase class which is derived from some other class which the code doesn't mention clearly.
Now to understand the big picture, i have also tried to create my own simple class, and tried to register an event, which i'll try to raise later (just for my own understanding).
Here is the code I have written:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
namespace WPFRoutedEvents
{
public class EventTest
{
private string variable = "Event has occured";
public static readonly RoutedEvent myTestEvent;
//Constructor
public static EventTest()
{
EventTest.myTestEvent = EventManager.RegisterRoutedEvent("TestEvent", RoutingStrategy.Bubble, typeof (RoutedEventHandler), typeof(EventTest));
}
public string getVariable()
{
return this.variable;
}
public event RoutedEventHandler myTestEvent
{
add
{
//Here is the problem
// I cannot use base.AddHandler () because it does not exist
}
remove
{
//Here is the problem
// I cannot use base.RemoveHandler() because it does not exist
}
}
}// end of class EventTest
}
Now since this class has not been derived from any class, i cannot access the base class function AddHandler.
My questions are the following:
1) Which class has the original AddHandler function implemented from which i need to extend my class?
2) Someone please briefly explain the pipeline from writing and event to finally setting it up to the point where it'll call the handler when it occurs, i.e starting from implementing an event, event handler, registering an event, defining the syntax of the event handler (coding part), and the pipeline from when en event occurs to until it is handled (actual execution of an event and event handler). It'll add more to my understanding of the text.
3) What i find in the book is ClickEvent which has already been implemented somewhere, it is created, registered, and finally handled. What i want to know is how will a programmer register some new type of event which has not yet been implemented (example could be triple click, just for the sake of example, otherwise i know it exists), and then register that event and then design a handler.
4) Is there any type of events, or some other equivalent, that occur on a particular state of a data (some variable, resource etc) instead of some input device event? Like for example while dragging to draw a line, it reaches a particular length?
Thanks!
The RoutedEvent system is centered around the UIElement class and its AddHandler method.
You should only create routed events in classes that inherit UIElement.
All other classes should use ordinary CLR events.
When you register a routed event, UIElement will prepare to store handlers for the event in instances of your class.
When you call AddHandler, UIElement will add the handler to something like a Dictionary<RoutedEvent, Delegate>.
When you add an event handler in XAML, the generated MyFile.xaml.g.cs code will add the handler using the CLR event accessor.
When you call RaiseEvent, UIElement will loop through its dictionary and call each handler.
For more information about field-like and custom events in C#, see my blog.

Categories

Resources