Custom events in Expression Blend - c#

I am developing my own FTP client and I want to create a nice GUI using expression blend. I was wondering how to create a custom event so that I can trigger an animation when an upload completes. In other words, is there a way I can subscribe to an even in expression blend/ create my own event? Thanks for the help.

Just put a new public property called bool DownloadCompleted { get; set; } in your ViewModel, and then use a ControlStoryboardAction with a DataTrigger to watch for a change in the DownloadCompleted property to true ... the animation will then be started.
There's a good explanation how to do it here.
http://www.basarat.com/2011/05/expression-blend-starting-storyboard.html
http://www.silverlightbuzz.com/2009/10/12/animating-with-storyboards-in-blend/
There's no need to create your own Event to notify of the completed download, however, you can do that if you wish...just choose an EventTrigger instead...and point the SourceName to the named element that's in your XAML that either has the event raised on it or (if it's a bubbling event, then you have the flexibility of watching the event on other elements....as long as the event bubbles through them).

Related

Xamarin Forms Event Bubbling and Invoking Operations on a Custom Renderer

I am creating a custom Xamarin Forms control that contains three buttons (1,2,3) inside a view. Let's just call it a GaugeView for the sake of this example. Here is how it is currently setup:
The GuageView has a custom renderer on both iOS and Android called GuageViewRenderer.
The GuageView exposes event handlers for Clicked1, Clicked2, and Clicked3.
The GuageView exposes ICommand properties for Click1, Click2, and Click3.
The problem is, I need to fire the event handlers from the custom renderer because only the native platform control knows when one of the buttons has been pressed. How do you bubble the events back up to the GuageView, which is where the shared code lives?
I was planning to wire up the commands and the event handlers down inside the custom renderer, but I'm having a heck of a time with it since events can only be fired from within the original class (GuageView).
Is there a better way to structure this? The main thing I am trying to do is expose the platform native guage and wire its buttons up so the event handlers in the shared code (GuageView) gets the event firings.
Right, you can't raise events outside of the class that declares them. So you'll have to add a method to GaugeView that will raise the events. I would also have that same method invoke the commands as well. So in GaugeView
public void RaiseClick1() {
var clicked1 = Clicked1;
if (clicked1 != null)
clicked1(this, EventArgs.Empty);
if (Command1 != null && Command1.CanExecute(Command1Paramter))
Command1.Execute(Command1Parameter);
}
Then in GaugeViewRender whenever you need to notify the view that a button was clicked:
Element.RaiseClick1();
Late answer but maybe for the future: You can raise the click event of a button from outside using the IButtonController interface.
The Xamarin.Forms.Button class implements this interface which provides one single method: SendClicked
By casting your Xamarin.Forms element in the renderer (this.Element) to IButtonController you're able to call this method and raise the clicked event of the Xamarin.Forms.Button.
I also created a blog post about this topic: http://software.fauland.cc/?p=5637

Is there a way to stop the WinForms designer defaulting to control Load event

This drives me nuts. In the Visual Studio WinForms designer, if you double-click a control it will produce a XXXX_Load handler for that control. This is never, ever, what you want. You want Click event or a Changed event or more likely to go to the existing Click event. You do NOT was a new Load event. It is worse because a double click can happen by accident. You click once, then again - bingo a Load event handler. I use a pen-tablet combo and double clicks are very easy!
Can someone tell me if there is a way to stop this happening. I would like a Click handler. I would settle for nothing happening.
One way to achieve that is inheriting the control and modifying the DefaultEventAttribute.
Specifies the default event for a component.
[DefaultEvent("Click")]
public class MyRadionButton : RadionButton {
}
But some care/extra work may need to be done when you override a control. You need to keep that in mind when using this approach.
In addition to Mehrzad's answer, you can completely disable it by passing an empty string to the DefaultEvent attribute:
[DefaultEvent("")]
public class MyCustomControl : UserControl
{
}
This works because the default control designer uses the ComponentDesigner.DoDefaultAction when the control is double clicked. By default, this uses reflection to look up the method signature of the default event. If it can't find it, it doesn't do anything.

How define priority for events in c#?

I'm developing a Windows Phone app using Map Control. Map control has CenterChanged and ZoomLevelChanged events.
When I change the zoom value for map, both events are raised (because the center changes as well).
But I want using only ZoomLevelChanged event, when I change zoom value.
How do I set priority for events if multiple events are available or how switch off CenterChanged event when ZoomLevelChanged is raised?
Any Solution/Demo/Link would be very much helpful for me.
You cannot define the priority for events, and you can't depend on the order of events.
I'm not a Windows Phone developer, but ask yourself: what if there were a zoom change at the same time as a large center change? You would need to handle both events, right? I would make that work, then make it work for the case of a zoom change with a small center change.
Events that happen "simultaneously" are added to the Dispatcher queue. If a single event sets "zoom" and then "center", the queue will contain the zoom event followed by the center event.
I'm not completely sure what you mean by defining priority. If you mean changing the order the event handlers are called, the only way to do this would be to modify the code that sets the two properties so that they are set in a different order. Once the event handlers are added to the queue, you can't reorder them.
If you want to handle only the first "simultaneous" event though, this should be possible by disabling the other handler until the end of the queue. Something like this:
// in ZoomLevelChanged handler:
_zooming = true;
mapControl.Dispatcher.BeginInvoke(new Action(() => _zooming = false));
// in CenterChanged handler:
if (_zooming) return;
// rest of implementation
BeginInvoke adds the action to the end of the queue, so the _zooming flag will only be reset once the immediate CenterChanged handler has been called and skipped, allowing subsequent CenterChanged events to be handled normally.

What is involved in adding my own event to WPF controls?

I'm constantly having to use TouchDown/TouchUp events here in my WPF project to detect a 'double-tap'; sometimes on a listbox, sometimes a button, sometimes a telerik control. How would I go about adding a DoubleTap event and event handler to these controls? Too big of a job?
You could create a class that is constructed with a reference to the control and a delegate function. (Please forgive my not perfect syntax [if it isn't perfect], I am typing this from memory)
public class DoubleTap {
delegate void ActionFunction();
Control ReferencedControl;
public DoubleTap ( ref Control referencedControl , delegate actionFunction ) {
ActionFunction = actionFunction;
ReferencedControl = referencedControl;
// apply TouchDown and TouchUp event handlers to ReferencedControl
}
// Put your TouchDown and TouchUp functions for testing the double tap here
// when double tap tests as true then call ActionFunction();
}
You will have to use behaviors for this.This will include creating derived type from System.Windows.Interactivity.Behavior and override OnAttached method for TouchDown/TouchUp.
See WPF Tutorial | Behaviors and Introduction to Attached Behaviors in WPF for how to implement behaviors.

What is the last event to fire when loading a new WPF/C# window?

I am trying to load a preferences window for my application and I would like the apply button to initially be disabled, then when a preference is updated, the apply button gets enabled again. I have some controls data bound to a preferences object and what happens is that after the window loads, the combobox events get triggered. Is there any event that is guaranteed to happen dead last after everything is stable?
Here is what my code looks like (the apply button is always enabled after the window loads):
private void Window_Loaded(object sender, RoutedEventArgs e)
{
_preferencesData = new PreferencesDataContext();
LayoutRoot.DataContext = _preferencesData;
ButtonApply.IsEnabled = false;
}
private void ComboBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
ButtonApply.IsEnabled = true;
}
Is it also interesting to note that this only happens with textboxes and comboboxes, not checkboxes or radiobuttons.
Best solution for simple need
Joseph's answer is the best solution by far for your simple need: Just use data binding and let the data model handle it.
Answer to question as posed
There are more complex scenarios when you really do need control after absolutely everything has finished loading and all events have fired. There is no single event that occurs "dead last", but it is easy to effectively roll your own using the Dispatcher queue.
This is how to do it:
Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action(() =>
{
var x = ComputeSomething(1, 2, 3);
DoSomething(x, "Test");
}));
Everything inside the { } will be executed when WPF finishes everything at a higher priority than ContextIdle, which includes all event handlers, loaded events, input events, rendering, etc.
Sequence of events when a Window is created and shown
As requested, here is the sequence of major events in WPF when a window is created and shown:
Constructors and getters/setters are called as objects are created, including PropertyChangedCallback, ValidationCallback, etc on the objects being updated and any objects that inherit from them
As each element gets added to a visual or logical tree its Intialized event is fired, which causes Styles and Triggers to be found applied in addition to any element-specific initialization you may define [note: Initialized event not fired for leaves in a logical tree if there is no PresentationSource (eg Window) at its root]
The window and all non-collapsed Visuals on it are Measured, which causes an ApplyTemplate at each Control, which causes additional object tree construction including more constructors and getters/setters
The window and all non-collapsed Visuals on it are Arranged
The window and its descendants (both logical and visual) receive a Loaded event
Any data bindings that failed when they were first set are retried
The window and its descendants are given an opportunity to render their content visually
Steps 1-2 are done when the Window is created, whether or not it is shown. The other steps generally don't happen until a Window is shown, but they can happen earlier if triggered manually.
The Window.ContentRendered event fulfilled my requirements.
I just did kind of the same thing behaviorly in a systray WPF app.
However, I didn't do it using event handling. I simply bound the Enabled property of my button to a property in my ViewModel, and had the property updated whenever I needed the behavior.
You can use ManagedSpy to figure this out on your own.
http://msdn.microsoft.com/en-us/magazine/cc163617.aspx
Setting the DataContext will likely fire the SelectionChanged event, and you can't rely on when exactly it's fired. Some logic checking on what exactly is selected would be more reliable:
private void ComboBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (myComboBox.SelectedItem == null)
{
buttonApply.IsEnabled = false;
}
else
{
buttonApply.IsEnabled = true;
}
}
The reason it's happening afterwards with your code as-is is because the event gets queued on the thread for the UI, so it's up to Windows if it will execute the next line of code in Load, or to handle the other events on the queue.
Not to throw a whole lot of stuff at you that you may or may not be familiar with, but if this is a relatively new codebase, you may want to consider using the MVVM pattern and use Commands instead of the archaic (emphasis mine) eventing model.
Order of Events in Windows Forms
Control.HandleCreated
Control.BindingContextChanged
Form.Load
Control.VisibleChanged
Form.Activated
Form.Shown

Categories

Resources