I have some user controls. The hierarchy is as follows:
A contains B
B contains C
Inside my C control I have a button. When I click on it want my event
public event EventHandler Print;
to by raised and then I want control A to catch this event. How can I do this?
EDIT 1:
I want to raise my event on User Control C's ViewModel
There are 2 topics that can help you fulfill your need:
Commanding
and
Routed Events
Both mechanisms are built specifically for wpf's hierarchical structure.
Read up on both, they will help your wpf experience immeasurably.
EDIT: Something more helpful. Put Button.Click="" on the control where you want to catch the event. You can use the button's Tag property to store identifying information so your event handler knows that the correct button was clicked.
<Grid Button.Click="Button_ClickHandler">
<Button Tag="PrintButton/>
</Grid>
In your code behind for the user control you will require the handler named Button_ClickHandler.
The above method uses Router Events. I really recommend using Commands however.
You can wrap the event like so:
class B
{
private A a;
public event EventHandler Print
{
add { a.Print += value; }
remove { a.Print -= value; }
}
}
I think you want to look at bubbling events.
Update: I didn't see the wpf tag, you should be looking at routed events
Related
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.
My UserControl contains various controls. I made an event handler for its click event. I want the event handler to fire / be called when the user clicks anywhere on my user control.
This is the method I use to add my UserControl to my WinForms application.
private void addContact(some parameters here)
{
//This is my usercontrol
contactsListItem.contactsListItem contact = new contactsListItem.contactsListItem();
//
//some codes here
//
//Adding an event handler for the click event
contact.Click += new EventHandler(contact_Click);
//Adding the UserControl to my application
flowLayoutPanel_contactsList.Controls.Add(contact);
}
The contact_Click(...) event handler should change the background of my UserControl. I have tried stepping into the code to see if the event handler fires and I found out that it doesn't fire no matter where I click on my UserControl.
I have searched through the internet. I encountered terms like delegate, subscribers and publishers.
What should I do to make the event handler for my UserControl's click event to fire?
What is the structure of your user control? Click events are not bubbled in WindForms, hence if you are clicking on a control WITHIN your user control, the latter won't fire any Click event.
EDIT:
The simplest solution is to manually bubble the event from each child by attaching a handler in your user control:
child1.Click += new EventHandler(child_Click);
child2.Click += new EventHandler(child_Click);
child3.Click += new EventHandler(child_Click);
and inside child_Click fire off your Click event:
this.OnClick(e);
You seem to be on the right track however it is not clear what your contact here is. Typically you use delegates (essentially pointers to functions) for methods that have arguments to be passed:
if (bDeleteRdClick)
DeleteRD.Click -= delegate { DeleteRDClick(this.Object); };
DeleteRD.Click += delegate { DeleteRDClick(this.Object); };
where you are sure to remove pre-existing delegates, otherwise they will 'stack-up', firing multiple methods when not required.
For the method above, using an EventHandler seems to me to be the right approach, but as I state above, a check on whether contact is of the correct type would not go unmissed:
if (this.contact.GetType() == typeof(RibbonButton))
{
RibbonButton Rb = (RibbonButton)contact;
Rb.Click += new EventHandler(contact_Click);
}
I hope this is of some help.
In C# events were always very protected: Only the owner of the event could trigger them. However, this seems to be completely different in WPF - Anyone can throw any event at any time. To test that, I've written the code in the bottom.
When I used RaiseEvent to raise Button.Click, the event above caught it. Is that the planned behavior of WPF events? Just letting anyone throw any events they wish? Also, if so, then what is the meaning of the OwnerType when you register the event? I thought it is some kind of protection, yet if it is, it is a poor one since anyone can access the public event and use AddOwner function to add more owners.
Thanks!
XAML
<StackPanel Button.Click="ButtonBase_OnClick">
<Button Name="RealButton">Real button</Button>
<WpfWindow:VitalyControl MouseDown="UIElement_OnMouseDown">
I am almost a button
</WpfWindow:VitalyControl>
</StackPanel>
Code behind
The custom control:
class VitalyControl : Label
{
public VitalyControl()
{
this.MouseDown += new MouseButtonEventHandler(VitalyControl_MouseDown);
}
void VitalyControl_MouseDown(object sender, MouseButtonEventArgs e)
{
RaiseEvent(new RoutedEventArgs(Button.ClickEvent, this));
}
}
And the handler:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
MessageBox.Show("Button was pressed");
}
This is by design, and is actually one of the reasons for RoutedEvents. They are called routed events because they are routed across the element tree. The behavior you are experiencing is called 'singular handler attachment point' on msdn. You specify that StackPanel should listen to all Button.Click events.
In your custom control, you raise a button click event. This 'bubbles' up to the stackpanel, which handles it.
UPDATE:
For this routing to work, I assume every UIElement needs to be able to raise any routed event. Routed Events are only used by UI elements, and are an answer to complexities with WinForms implementations. They aren't a replacement for CLR events.
The owner type is used internally when resolving an event by name.
I've got a custom control we'll call "TheGrid".
In TheGrid's controls is another control we'll call "GridMenu".
GridMenu has a button control in its own control collection.
I'd like to enable the developer using this control to associate a page level method with the OnClick of that button deep down inside GridMenu ala:
<customcontrols:TheGrid id="tehGridz" runat="server" onGridMenuButtonClick="mypagemethod" />
On the GridMenu (which I assume is another custom control), expose the event ButtonClick by declaring it as public:
public event EventHandler ButtonClick;
If you like, you can create a custom event handler by defining a delegate, and a custom event argument class. Somewhere in the logic of this control, you will need to raise the event (perhaps in the Clicked event handlers of buttons contained on GridMenu; events can cascade). Coding in C#, you'll need to check that the event is not null (meaning at least one handler is attached) before raising the event.
Now this event is visible to TheGrid, which contains your GridMenu. Now you need to create a "pass-through" to allow users of TheGrid to attach handlers without having to know about GridMenu. You can do this by specifying an event on TheGrid that resembles a property, and attaches and detaches handlers from the inner event:
public event EventHandler GridMenuButtonClick
{
add{ GridMenu.ButtonClick += value;}
remove { GridMenu.ButtonClick -= value;}
}
From the markup of a control containing a TheGrid control, you can now specify the event handler by attaching it to OnGridMenuButtonClicked the way you wanted.
You can register an event handler for this event using delegates. See the following MSDN articles:
http://msdn.microsoft.com/en-us/library/system.eventhandler%28VS.71%29.aspx
http://msdn.microsoft.com/en-us/library/aa720047%28v=VS.71%29.aspx
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