the name of event for add or remove the children of inkCanvas using wpf - wpf

I have an Inkcanvas in my project (myPaint)
What is the name of event for add or remove the children (UiElement) from InkCanvas. for example I want handle this event : myInkCanvas.Children.remove(myRectangle) or this example :
myInkCanvas.Children.Add(myRectangle)

There isn't an event you can listen to that is fired when elements are added to or removed from the Children collection. There is a virtual protected method that is called, which you could leverage, called OnVisualChildrenChanged.
This isn't directly tied to the Children collection, as elements can add/remove visuals separate from that. But for InkCanvas, it would probably be safe.
So you'd use something like:
public class MyInkCanvas : InkCanvas {
protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved) {
// TODO: Raise event or do something
base.OnVisualChildrenChanged(visualAdded, visualRemoved);
}
}

What exactly do you need this for? Can you use the StrokeCollected event instead?

Related

How to subscribe to an event in a child usercontrol in Silverlight?

I've got a usercontrol (MyUC) that is programatically added to a page (MainPage) several times.
In MyUC I set the DataContext to a view model like this:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
DataContext = new MyUCViewModel();
}
In my view model (MyUCViewModel) I have a collection of data items:
public MyDataItemCollection MyDataItems { get; private set; }
And in the constructor I have:
public MyUCViewModel()
{
this.MyDataItems = new MyDataItemCollection();
this.MyDataItems.ChosenItems.CollectionChanged += new NotifyCollectionChangedEventHandler(ChosenItemsChanged);
this.MyDataItems.Add(new DataItem());
}
From the above MyDataItems has another collection in it for ChosenItems and I added a NotifyCollectionChangedEventHandler to it.
Other parts of my code add and remove from the ChosenItems collection and that part seems to work ok.
Next I have the event handler method in the view model:
private void ChosenItemsChanged(object sender, EventArgs e)
{
MessageBox.Show("Chosen Items Changed");
}
This also works and I get a messagebox everytime the user makes a change in the UI that affects the ChosenItems collection.
The part I'm trying to figure out now is how do I set it up so that my MainPage does something when the ChosenItemsChanged event fires in my user controls. What I want to do is have the MainPage loop through the generated MyUC controls on the page and make each usercontrol call a method.
You can add more event listeners in the MainPage like this:
MyUCViewModel viewModel = myUC.DataContext;
viewModel.MyDataItems.ChosenItems.CollectionChanged
+= new NotifyCollectionChangedEventHandler(MainPage_ChosenItemsChanged);
This is based on the comment as the question was a little misleading:
While not strictly MVVM, as your question appears to be, your should write your User Controls as if it was a third-party control and simply expose a custom event on it. User Controls should always be a black-box with a public interface. For a reusable control that is self-contained (as many are) MVVM is overkill.
e.g.
in your User Control add:
public event EventHandler<MyEventArgs> MyEvent
Create a MyEventArgs class deriving from EventArgs and get it to hold useful parameters (like the selected item).
In your main page add a handler to MyEvent on each User Control you dynamically add.
I actually think the MVVM model is flawed and all this sort of controlling logic and event handlers belong in a Controller class (MVCVM!), but that's another story. :)

Difference between normal customized event the static RoutedEvent

Please check the code below which defines the same scroll event in two different ways:
---------------------------------normal way--------------------------------------
public event RoutedEventHandler CloseTab;
------------------------------static RoutedEvent---------------------------------
public static readonly RoutedEvent CloseTabEvent =
EventManager.RegisterRoutedEvent("CloseTab", RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(CloseableTabItem));
public event RoutedEventHandler CloseTab
{
add { AddHandler(CloseTabEvent, value); }
remove { RemoveHandler(CloseTabEvent, value); }
}
1.What's the difference between the normal customized event and the static RoutedEvent?
2.Why the event in the first way can be raised by a method like "if(CloseTab!=null){CloseTab(o,e);}",but in the second way ,it only can be raised by the UIElement.RaiseEvent() method?
3.I know this question must be very very silly,but it dose make me confused.
It is that Why the event in the first way can be raised by the "if(CloseTab!=null){CloseTab(o,e);}" method only in the class which the event is defined?And when it is outside the owner class,the event can only add or remove handlers with "+=/-=" ?
Thanks for your time!!
You implementation basics i.e. the way we raise each one differently, are correct.
But apart from that, as far as my knowldge on routed events goes...
The first is NOT a routed event. It is a simple CLR event declared with its type as the RoutedEventHandler delegate. When this event is raised it will not bubble \ tunnel up to the ancestor/child UI elements respectively.
At practical level, I guess if you try using the first one in EventTrigger it will not work.

OnClick event on compound UserControls

I want to create a UserControl with several controls inside. These controls should behave simmilar to the radio buttons, i. e., the status of one of them affects the status of the rest. To do that I would like to be able to handle the OnClick event on each of the controls from the parent.
One solution could be to call a method of the parent, to perform the global UserControl change, from the child controls' OnClick method. Something like:
class Child : UserControl
{
...
protected override void OnClick(EventArgs z_args)
{
// do own stuff
((PartentType)Parent).ChangeStatus(this);
}
...
}
This is a solution, but I wonder if there is a more standard an elegant way to solve this issue. Thanks!
No, this is very bad, a control should never depend on having a specific parent. Do it the same way any Windows Forms control does it: if something interesting happens that a parent might be interested in then raise an event:
public event EventHandler StatusChanged;
public int Status {
get { ... }
}
protected override void OnClick(EventArgs z_args) {
// do own stuff
//...
var handler = StatusChanged;
if (handler != null) handler(this, EventArgs.Empty);
}
Consider putting the event raising code in a private setter for the Status property.

How to add event handler to an inherited winform control?

I need to add an event handler to an inherited control like a datagridview but Visual Studio doesn't allow me. Isn't there a way for an inherited control to fire a base event handler AND the inherited one? in a sequence I specify?
Your question is unclear. Assuming that you're trying to handle the base class' event in the inherited control, you can override the OnEventName protected virtual method. In the override, make sure to call the base method or the event won't fire.
This method exists (AFAIK) for every event in every control in System.Windows.Forms. If the control you're inheriting does not have this virtual method, you can subscribe to the vent in the constructor.
For example:
class MyButton : Button {
//First way
protected override void OnClick(EventArgs e) {
base.OnClick(e); //Without this line, the event won't be fired
//...
}
//Second way
public MyButton() {
base.Click += Base_Click;
}
void Base_Click(object sender, EventArgs e) {
//...
}
}
EDIT:
If you're trying to raise the base class' event, you can call these OnEventName methods.
If the base class doesn't have one, the only way to do it is to declare a new event, and add a handler to the original event from the base class that raises your new event. Note that if you have other code that uses the base class' event, and the evnet is not virtual and doesn't have a raiser method, you're out of luck, unless you can decompile the base clas and find out where the event is raised.
Events in WinForms typically have a corresponding "On*" method. Simply call that method, and it'll raise the event. If you want to raise "CellClick" for example, call "base.OnCellClick(new DataGridViewCellEventArgs(row, column))".

WPF Custom Routed event question

How do you get two unrelated controls to raise the same custom event? All examples I have seen so far have an event defined within a single control, should I be taking a different approach?
Eg. I'd like to raise a custom bubbling event from an OnFocus handler for a button and a textbox.
First off let me say your question doesn't make it clear that you don't want to use the existing UIElement.GotFocusEvent, but I'll assume you know about it and have your reasons for not using it.
You can always register a custom event on a static class, and raise it wherever you want. The Keyboard class does with all of its events (e.g. Keyboard.KeyDownEvent).
public static class RoutedEventUtility
{
public static readonly RoutedEvent MyCustomEvent = EventManager.RegisterRoutedEvent("MyCustomEvent", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RoutedEventUtility));
}
You raise the event just like you would any other RoutedEvent.
RoutedEventArgs args = new RoutedEventArgs(RoutedEventUtility.MyCustomEvent);
RaiseEvent(args);
If you want another class to own the event as a public field then you will need to add an owner.
public class MyCustomControl : Control
{
public static readonly RoutedEvent MyCustomEvent = RoutedEventUtility.MyCustomEvent.AddOwner(typeof(MyCustomControl));
}

Resources