I've create a WinForms control that inherits from System.Windows.Forms.UserControl...I've got some custom events on the control that I would like the consumer of my control to be able to see. I'm unable to actually get my events to show up in the Events tab of the Properties window during design time. This means the only way to assign the events is to programmatically write
myUserControl.MyCustomEvent += new MyUserControl.MyCustomEventHandler(EventHandlerFunction);
this is fine for me I guess but when someone else comes to use my UserControl they are not going to know that these events exist (unless they read the library doco...yeah right). I know the event will show up using Intellisense but it would be great if it could show in the properties window too.
Make sure your events are exposed as public. For example...
[Browsable(true)]
public event EventHandler MyCustomEvent;
A solution using delegate. For example i used for a custom ListView which handle item added event :
Declare your delegate :
public delegate void ItemAddedHandler(object sender, ItemEventArgs e)
then declare the event which use the delegate :
[Browsable(true)]
public event ItemAddedHandler ItemAdded;
Note : ItemEventArgs is a custom EventArgs
Hope can help you, works fine for me
Related
I was a stubborn WinForms protectionist for years, but I changed my mind and try to get in touch with WPF. I like it so far.
My problem:
I've created a UserControl "SelectableRectangle" which Contains a Rectangle. Well - in one of my application I create hundreds of them, programmatically/dynamically.
And I want to be able to "click" on them and use different tools, for example changing the color. Therefore I need to know in my main window on which exact SelectableRectangle I clicked.
Any ideas?
Basically, if your usercontrol implements an event handler you can link an event-handler to an event like that:
mycontrol1.Click += new RoutedEventHandler(mycontrol_Click);
and then implement the method
private void mycontrol(object sender, RoutedEventArgs e)
{
// do things here
}
Further, if your usercontrol is derived from either UIElement, UIElement3D or ContentElement you can use the AddHandler method:
mycontrol1.AddHandler(Button.ClickEvent, new RoutedEventHandler(mycontrol_Click))
I'm working on a semi-professional project and needed a custom view for one of my models. As far as I could figure out that meant creating a UserControl-inherited class, like so:
public partial class PopulationView : UserControl
{
...
}
Now this works wonders, and I've been able to do pretty much all I wanted, including custom painting with onPaint but I've noticed none of the events seem to be registering. I've had to attach multiple event listeners and in all instances I end up going back to my form and adding an event listener to my custom component's instance in the form. For example, I'd like to add a Click event listener. What I try first is simply
public partial class PopulationView : UserControl
{
private void PopulationView_Click(object sender, EventArgs e)
{
Debugger.Break();
}
}
of course attaching the function to the Click event through PopulationView.cs [Design]. That doesn't work so I end up adding a Click event listener on the instance of the component and adding the PopulationView_Click function to my form (MainForm.cs [Design]) instead and launching the appropriate function on the control.
I feel that I'm missing something very simple which is preventing me from being able to register events in my control directly and I'd appreciate any help with this. I dug around the interwebs but couldn't find anything relevant.
Update
Some of the comment make me think I should provide more detailed information about what I'm doing. The setup is sort of complicated but here's a summary:
I have a custom control inheriting from UserControl, called PopulationView
I have an instance of that control added to a form
Attaching event listeners through the design view of the form to the instance of the control (listener in form itself) works. Adding them through PopulationView's design view (listener in PopulationView) does not.
What complicates thing is I have a BackgroundWorker in my form which is in charge of generating the PopulationModel for the PopulationView. Once that BackgroundWorker is done, it uses a BeginInvoke to tell the PopulationView it's time to draw.
However, all events behave the way described even before the BackgroundWorker is triggered with RunWorkerAsync. Is it possible it's still interfering?
Editing the PopulationView constructor, I had accidentally deleted the call to InitializeComponent(), where all the Designer code was. Silly, really. If you're ever using the Designer, make sure you call InitializeComponent from your constructor.
Sorry first, because I see another question, but both of the ans. and ques. is not clear enough
How can I raise a parent event from a user control in WPF?
In my MainWindow.xaml, I had a right Panel
<local:RightSideContent x:Name="RightPanel" Grid.Column="1">
So in the MainWindow.xaml.cs, if I want rise an event to this panel, I made the code like this:
public delegate void Event1();
public MainWindow()
{
this.InitializeComponent();
Event1 obj = new Event1(this.RightPanel.func);
obj();
// Insert code required on object creation below this point.
}
And in RightPanel class, I declare the function func
The question is: if I am in the RightPanel Class, how I raise an event to the MainWindow, because I can't wrote something like this.RightPanel.func.....
And by the way I am in another class that do not have xaml file, if I want raise an event to a UserControl, how can I do?
Sorry, I don't quite have enough rep to post a comment to clarify, but as I see it, there are three possible things you are trying to do here.
You are trying to trigger an event on MainWindow, from some code that doesn't reside in MainWindow. In which case, you need to make sure that you have a reference to MainWindow, and that there is a public method on MainWindow that will trigger that event.
You want MainWindow to handle a click etc that comes from RightPanel. In that case you simply put a Button.Click="blah" (or whatever the event is) attribute on your MainWindow, and it will catch any button clicks from below it that are not handled lower down. In fact you can even handle it lower down and make sure that you set the EventArgs so that it is effectively unhandled, so that you can then handle it higher up as well.
You want to be able to handle a custom event generated in RightPanel, in a similar way to the way you would the button click scenario from item 2 above. In this case, I would direct you to http://msdn.microsoft.com/en-us/library/ms742806.aspx which is the documentation for Routed Events in WPF, and you should be able to work out how to create your own RoutedEvent from there.
How can I register to event and do some actions at runtime?
For example when the user click on a button I want to register to OnMyEvent and run MyFunc that let's say initialize some textBox with the OnMyEvent args.
I'm using winforms and .NET 4.
EDIT
Maybe I was unclear... I need the ability to register to existing event and add a new method that will run when the event will fire. All at runtime.
EDIT2
i'll try to give an example...
lets say that i have a class named "A" that have many events OnDataRecived OnDataSend etc...
when the application running the user can choose form a combobox event name to register (i got the events list via reflection because they not constracts, they are generated from xml file) and which data to update when the choosed event is fired.
so for the example the user choose to register to the OnDataReceived and he choose to update property named DataStream. some code...
in run time upon user choosing:
A.OnDataReceived += (s,e) => MyRunTimeMethod(s,e);
private void MyRunTimeMethod(object sender, EventArgs e)
{
DataStream = e.Data.Value
}
You are asking how to create a method dynamically at runtime - once you have a reference to that method in a delegate, the question of how to register it to an event is trivial.
MSDN describes how to do this with MSIL instructions. I doubt that's what you're looking for, but it is an option.
The C# FAQ blog has a much more interesting solution using expression trees. I suppose this is the one you were referring to by originally tagging your post with expression-tree.
But I would reconsider using dynamic methods at all. How exactly is the user going to specify what action to perform on the event of his choice? I suspect that the options are limited enough that you can get by with something simpler:
protected void btnRegister_Click(object sender, EventArgs e) {
switch (cmbEvents.SelectedText) {
case "OnLoad":
MyControl.OnLoad += (s, e) => SomeSelectedControl.Text = SomeInputControl.Text;
break;
//... other cases
}
}
If you're using windows forms, double clicking a button will bring you to a created on_click event. If you bring up the properties window for the button, theres an events tab. Viewing this will show you which events are available for a control.
I found the best way to understand this, was to look at the code created when adding the events.
Update:
As noted, I completely missed the point with my answer. The syntax for subscribing to an event at runtime is the same way as it's done on form Initialize. So I don't get any terminology wrong, here's the link to the msdn documentation;
http://msdn.microsoft.com/en-us/library/ms366768.aspx
What you want to achieve, does not require you to "Register to event at run time".
If button1 is the button of interest here, simply use.
button1.Click += buton1_ClickHandler;
button1_ClickHandler should be defined in the same class as your button1. and it should have the signature of the RoutedEventHandler. So, it should be
private void button1_ClickHandler(object sender, RoutedEventArgs e)
{
//method code here
}
I need to change a certain DataGridView's property (a DataSourceUpdateMode for one of its binding) only when ALL of its initial data bindings are completed.
I tried subscribing to the "DataBindingComplete" event, but it's fired too many times (one or more time for each binding associated to the control); what I need is a more global "AllDataBindingsComplete" event, fired when the control is ready to be displayed to the user.
As a temporary workaround, I'm using the MouseDown event (I've assumed that when the user is able to click the control, it means that the control is displayed... :) and the events I'm playing with - SelectionChanged - are fired after the MouseDown):
protected override void OnMouseDown(MouseEventArgs e)
{
Binding selectedItemsBinding = this.DataBindings["SelectedItems"];
if (selectedItemsBinding != null)
{
selectedItemsBinding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged;
}
base.OnMouseDown(e);
}
It works, but it smells like an ugly hack A LOT (and it's called too many times, only one time is enough for my needs).
Is there a better way?
(yes, I'm trying to adopt MVVM in a Windows Forms project, and I've added a bindable "SelectedItems" property to the DataGridView...)
What I've done at the Windows Forms form level, and may be improvised down to just the control(s) you want, is to subclass the Windows Forms baseclass into my own. Then, in its constructor, attach an extra event call to the Load() event.
So when everything else is completely loaded, only THEN will it hit my custom method (of the subclass). Since it is the bottom of the call-stack chain being attached to the event queue, I know it's last and everything else is done... Here's a snippet of the concept.
public class MyForm : Form
{
public MyForm()
{
this.Load += AfterEverythingElseLoaded;
}
private void AfterEverythingElseLoaded(object sender, EventArgs e)
{
// Do my own things here...
}
}
This concept can be applied to the Init() function too if that's more appropriate for your control... Let everything else within it get initialized(), then do you the "AfterInitialized()" function.