Rx with button tap and hold event in Windows Phone 8 - c#

I have a simple Windows Phone 8 app with a button and a textbox. How do I use Reactive Extensions for the button Tap and Hold event to change the TextBox text?
void AttachRx()
{
IScheduler cs = new DispatcherScheduler(Deployment.Current.Dispatcher);
Observable.FromEvent<System.Windows.Input.KeyEventArgs>(btn, "Tap").Throttle(TimeSpan.FromSeconds(.5), cs)
.Do(a => ChangeText()).Subscribe();
}
error message:
{System.InvalidOperationException: The event delegate must be of the form void Handler(object, T) where T : EventArgs.
at Microsoft.Phone.Reactive.Observable.FromEvent[TEventArgs](Object target, String eventName)
at PhoneApp4.MainPage.AttachRx()
at PhoneApp4.MainPage..ctor()}

There are a few issues to address here.
The error you've reported is specifically saying that the delegate you are trying to add to the Tap event is not compatible - which makes sense because I don't imagine the Tap event has a KeyEventArgs payload (I think it is GestureEventArgs)? You are also probably better off using Observable.FromEventPattern as used in my example below. It's easier as you can get away with inferring the EventArgs type.
Caveat - As I have only WP8.1 SDK on my laptop at the moment, I have only the Win RT Tapped Event which is different from Tap, so I've just read the docs on Tap and not run the example below.
Assuming a Button called btn and a TextBox called txt and a function string GetText() that gets the text to set, do this:
Observable.FromEventPattern<GestureEventArgs>(btn, "Tap")
.Throttle(TimeSpan.FromSeconds(0.5))
.Select(_ => GetText())
.ObserveOnDispatcher()
.Subscribe(x => this.txt.Text = x);
Note a few things here:
Use FromEventPattern when standard .NET events are available - it better suited for this than FromEvent which really exists to handle non-conforming delegates.
Don't use Do like this. It works as a side-effect and isn't really idiomatic functional reactive programming. Doing this is in general could also cause unintended problems in more complex queries. Instead, project the input event to the desired result with a Select.
Don't run the Throttle on the dispatcher - use the default scheduler (or parameterize for testability with .Throttle(TimeSpan.FromSeconds(0.5), Scheduler.Default). You don't need the Throttle to run on the dispatcher - it's better off in the background. You only want to transfer to the dispatcher when you are ready to update the UI.
If you import nuget package rx-xaml you can use ObservableOnDispatcher to grab the current dispatcher. Although, for testability, you may wish to use the overload of ObserveOn (also in rx-xaml) that takes a dependency object like the page you are running on - e.g. ObserveOn(this) if you set up the subscription in the page code-behind for example, the page itself will do.
The example above assumes that GetText is synchronous. If you need to make an asynchronous call to get the text you wish to display, use the following pattern (assuming that GetText has a Task<String> return type):
Observable.FromEventPattern<GestureEventArgs>(btn, "Tap")
.Throttle(TimeSpan.FromSeconds(0.5), Scheduler.Default)
.Select(_ => Observable.FromAsync(GetText)
.ObserveOn(this))
.Switch()
.Subscribe(x => this.Name.Text = x);
Note the strange looking placement of ObserveOn inside the Select. The reasons for this are quite complex to explain briefly (and I'm not sure how relevant it is to this question), but basically it avoids a race condition where if a long running async GetText call for an earlier event could over-write the results of a short running call due to a later event.

Related

Setup an event loop for a UWP app

How do I setup an event loop (main loop) in a UWP app?
My goal is to have an app that has a main page with a continuously updating calculation, that then continuously updates an image on the page. While that is constantly happening, the user can click a button to change the calculation behavior, or to go to a second page and edit related data.
The user can then click back to the main page and see the image and calculation restart and continuously update. (The calculation is complex, so it should go as fast as possible and use up as much app time as possible).
If there is a way to accomplish this without an event loop I would like to know that also, but so far I have not found a way.
With an event loop, I can simply update the calculation and UI every time through the loop. But I have not found any way to do so. This question asked nearly the same thing, but was never directly answered and had a different use case anyway.
The closest I have found to a solution is to grab the CoreDispatcher from the CoreWindow and use the RunIdleAsync() method to create a loop:
public MainPage()
{
this.InitializeComponent();
Windows.UI.Core.CoreWindow appwindow = Windows.UI.Core.CoreWindow.GetForCurrentThread();
Windows.UI.Core.CoreDispatcher appdispatcher = appwindow.Dispatcher;
//create a continuously running idle task (the app loop)
appdispatcher.RunIdleAsync( (dummyt) =>
{
//do the event loop here
.
.
.
if (appdispatcher.ShouldYield()) //necessary to prevent blocking UI
{
appdispatcher.ProcessEvents(Windows.UI.Core.CoreProcessEventsOption.ProcessAllIfPresent);
}
});
}
The main problem with this is that you can't switch between pages (you get a system exception from dispatching events within an already dispatched event).
Second, this is very messy and requires maintaining extra state in the event loop. Besides, why should I have to go through these contortions just to have some calculations happening while the app is waiting for user input?
Is there a way to do this (besides switching to a C++ DirectX app)?
I don't know about setting up your own event loop, but there is no reason to do so.
What you are talking about sounds like a great case for Tasks. You would start a calculation Task whenever your user did something, having it report its progress via standard C# events if you need mid-operation updates. Those updates would modify properties in your view model which the binding system would then pick up.
You could also make your calculation code cancellable so changes can abort a previous calculation.
All of this involves pretty standard UWP concepts; no need for a special event loop. That you are even considering that makes me think you need to study MVVM and multi-threading/tasks; you are still thinking in a very "Win-Forms" kind of way.
If we're talking about some event loop, or stream, .Net has a great library named Rx, or Reactive Extensions, which may be helpful for you. You can set up a simple flow, something like this:
var source = Observable
// fire event every second
.Interval(TimeSpan.FromSeconds(1), Scheduler.DispatcherScheduler)
// add timestamp for event
.Timestamp()
// gather system information to calculate
.Select(GetSystemInfo);
Note that the events right now are on UI thread, as you need to access the controls. Now you have two options: use Rx for background processing too or use TPL Dataflow' TransformBlock for processing your system information into new image (it can be Observer and Observable at a time). After that you need to get back to UI thread.
First option:
var source = Observable
// fire event every second
.Interval(TimeSpan.FromSeconds(1), DispatcherScheduler.Current)
// add timestamp for event
.Timestamp()
// gather system information to calculate
.Select(GetSystemInfo)
// expensive calculations are done in background
.Select(x => x.ObserveOn(DefaultScheduler.Instance))
.Select(x => Expensive(x))
.Select(x => x.ObserveOn(DispatcherScheduler.Current))
.Select(x => UpdateUI(x));
You probably should split this chain into several observers and observables, still the idea is the same, more information here: Rx Design Guidelines.
Second option:
var action = new TransformBlock<SystemInfo, ImageDelta>(CalculateDelta,
new ExecutionDataflowBlockOptions
{
// we can start as many item processing as processor count
MaxDegreeOfParallelism = Environment.ProcessorCount,
});
IDisposable subscription = source.Subscribe(action.AsObserver());
var uiObserver = action.AsObservable()
.Select(x => x.ObserveOn(DispatcherScheduler.Current))
.Select(x => UpdateUI(x));
I want to note that UWP and MVVM pattern do provide a possibility to work with binding between UI and ObservableCollection, which will help you to notify user in most natural way.

Reactive Extensions - Correct way to observe a Javascript call into C# wrapper

I am developing a C# WinForms application that contains a web browser control. The application contains a "scripting bridge" class that allows Javascript code to call into the web browser control (I need to know when certain functions are called in the JS code in order to perform some action in the WinForms application). Most of these operations are asynchronous because when I launch a request from the WinForms application, it will typically perform an ajax request within the JS code (not the C# code). Since this is an asynchronous operation, I was trying to come up with a better/easier way to manage the subscriptions/timeouts/error handling, etc. for these asynchronous events. I came across Reactive Extensions and decided to try it out.
I'm trying to determine if I am doing this correctly or not. I'm trying to wrap my head around Reactive Extensions. It's difficult to find simpler examples on the net for a lot of the Observable extension methods. Here is what I am doing right now:
public void SetupObservable()
{
IConnectableObservable<string> javascriptResponseObservable = Observable.Create<string>(
(IObserver<string> observer) =>
{
observer.OnNext("Testing");
observer.OnCompleted();
return Disposable.Create(() => Console.WriteLine("Observer has unsubscribed"));
})
.Timeout(DateTimeOffset.UtcNow.AddSeconds(5))
.Finally(() => Console.WriteLine("Observable sequence completed"))
.Publish();
IObserver<string> testObserver = Observer.Create<string>(
(value) => Console.WriteLine(value),
(e) => Console.WriteLine("Exception occurred: " + e.Message),
() => Console.WriteLine("Completed")
);
IDisposable unsubscriber = javascriptResponseObservable.Subscribe(testObserver);
}
// The following will be executed later (once the ajax request is completed)...
// Fire the event and notify all observables. If it took too long to get this point then the sequence will timeout with an exception.
public void OnSomeJavascriptFunctionCall()
{
// Somehow get the javascriptResponseObservable object...
javascriptResponseObservable.Connect();
}
I feel like I am doing this the wrong way or that there is a better way to accomplish this. For example, how do you retrieve the IObservable that was created earlier so that you can call more methods on it? Would I have to persist it in the class or somewhere else? It seems like a lot of the examples don't do this so it seems like I am doing something fundamentally wrong. Also, if several observers are subscribing to the IObservable from different classes, etc., again, how do you keep track of the IObservable? It seems like it needs to be persisted somewhere after it is created. Is there a Observable.GetExistingObservable() method of some sort that I am missing?
I feel like I am doing this the wrong way or that there is a better way to accomplish this.
Wrong is always a point of view, but I would argue, yes there is a better way to solve what you are doing.
I assume that your JavaScript bridge has some sort of way of raising events? And this is how it is able to call-you-back? If so, they you will want to leverage that call back and bridge that to Rx using either Observable.Create, Observable.FromEvent* or another Rx factory method.
That would be your first step, then you would need to pass your "commands" to your JS layer. This is where you would need to remember to subscribe to your callback sequence before you issue the command to mitigate any race conditions.
It is difficult to help any more, as you only show Rx code that seems to serve no purpose except trying to understand Rx, and no code that shows what you are trying to achieve in the C#-to-Js bridge. Please provide a "Minimum Complete Verifiable Example" - https://stackoverflow.com/help/mcve

How do I convert a ListView SelectedItem into an IObservable?

This may be a remedial question, but my research is spinning me in circles right now (especially as a Java developer) and looking at several different Rx wrapper libraries. All I want is to take a ListView<MusicNote>.SelectedItem and wrap it into an IObservable, emitting a stream of the current single selected value. What is the easiest means to do this? Should I use the ReactiveProperty, Rx-XAML, or some library? Or is there an easy built-in way to do this with Rx.NET? I would prefer to not use a traditional event method stub that VS generates. Although I could push values in that, it feels messy and is not the paradigm I want.
this.keySelector.SelectedItem // turn this ListView's SelectedItem into an IObservable
One way of doing it in Rx.Net is the following:
var whenSelectionChange = Observable.FromEventPattern(h => listView.SelectedIndexChanged += h,
h => listView.SelectedIndexChanged -= h)
.Select(_ => listView.SelectedItem);
Basically, FromEventPattern() generates an observable sequence from the SelectedIndexChanged events triggered by your ListView. The Select() will be called each time an event is triggered, so you can get the selected index from your list and return it. The whenSelectionChange will be an IObservable<int> where each added element is the new selected index.
I have never used it, but you can take a look at http://reactiveui.net/ It's a MVVM framework that seems to integrate well with RX.Net and it is supported on all mobile platforms.
Thanks for all your help guys. This is ultimately what I ended up doing. Although I didn't want to do it this way initially it seems to be the simplest. And here is the final product of my work https://goo.gl/HTF3zd
private readonly ReplaySubject<TuningChangeEvent> tuningChange = new ReplaySubject<TuningChangeEvent>();
private void OneTuner_ValueChanged(object sender, RangeBaseValueChangedEventArgs e) {
tuningChange.OnNext(TuningChangeEvent.tune(1,Convert.ToInt32(OneTuner.Value)));
}

How to run events sequentially in C# or Similar Frameworks

How to Cancel/Regulate event which is executing in parallel with same event in another thread.
For e.g. In a textbox, every time we enter a character the event fires if text changed event is defined. But after entering first character, the event (Let us call First Event) takes lot of time (as there will be more strings which match a single character), and does some action like changing content of a title label. And after entering a second character the new event which raised to run in parallel takes less time. So now, the second event which fired after entering second character executes fast and returns first and first event executes last and thus, first event's result will be printed ultimately on the label rather than the second one.
Is there a better way to cancel the first event before starting the second event. One thing that comes to my mind is to register threads on a global list variable and kill all threads which are not dead before starting your execution. Will this work?? Any better way to handle this situation.
P.S. I know that search could be initiated after a space or enter to solve this particular issue. But I think you have already noticed my main point. :)
My favourite library for dealing with this exact problem is Rx.Net with TPL. This behaviour can be easily implemented with a combination of a Cancellable Task with an event observer using Observable.FromAsync
Some code!
var textChanged = Observable.FromEventPattern(x => textBox.TextChanged += x, x => textBox.TextChanged -= x)
.Select(_ => textBox.Text);
IDisposable eventHandler = textChanged.Throttle(TimeSpan.FromMilliseconds(500))
.Select(text => Observable.FromAsync((TaskCancelationToken cancel) => DoSearchTaskAsync(text, cancel)))
.Switch()
.Subscrible(results =>
{
//Update the UI
});
Note there is no need to explicitly type any of this...I am only doing it for clarity, but I am more than likely to have mistyped a class name or two...
EDIT
The Search method would be the method body of Task<TReturn> DoSearchTaskAsync(string, TaskCancellationToken).
The magic sauce comes from the Observable.FromAsync and Observable.Switch.
Each time we have a change in the textBox.Text we fire an event. That is filtered by the .Throttle (as you would expect). The clever bit is when we then create a new event source on DoSearchTaskAsync using Observable.FromAsync. At this point we have an IObservable<IObservable<TResult>>, or another way to put it, an eventsource of an eventsource. The switch means we only want the results from the most recently sent eventsource from the outter eventsource, and kill (Dispose) the subscription of previous eventsources.
The act of disposing the previous Observable.FromAsync will cause the TaskCancellationToken to cancel, and prevent its results bubbling up, whilst we subscribe to the new Task.
All very clever stuff, and I only recently came across this AWESOME pattern (I would credit the author if I could).
As for the Observable.FromEventPattern that is pretty unfortunate, as of C#5, there are no first class eventhandlers, so we pass in a lambda for subscription and a lambda for de-subscription.
The .NET Task API has the concept of cancellation built in. See this page for an example and links to more information. http://msdn.microsoft.com/en-us/library/dd997396(v=vs.110).aspx

I need some explain on Rx behavior

When I use Reactive Extensions (Rx) with linq filter what happen under the hood?
Is this,
var move = Observable.FromEventPattern<MouseEventArgs>(frm, "MouseMove");
IObservable<System.Drawing.Point> points = from evt in move
select evt.EventArgs.Location;
var overfirstbisector = from pos in points
where pos.X == pos.Y
select pos;
var movesub = overfirstbisector.Subscribe(pos => Console.WriteLine("mouse at " + pos));
more efficient from this?
private void MouseMove(object sender, EventArgs args)
{
if (args.Location.X == args.LocationY)
Console.WriteLine("mouse at " + args.Location);
}
I dont talk about the filtering logic itself but about the events behavior of the methods.
In Rx do the event raised exactly the same way of the regular event but with warapper or there is somthing special under the hood?
In this case, there's no algorithmic performance benefit for using the Rx query over the typical event handler - in fact, your Rx query may actually be marginally slower than the typical event handler. "Under the hood" the Rx query is basically doing the same thing as the typical event handler, but in a cleaner way.
The Rx query is not more efficient than the directly subscribing the events. Under the hood, the Rx query is still subscribing to the events and adding a bit of logic (e.g. for the schedulers), so I would say you are trading a bit of performance for increased readability, flexibility (since you can quickly change and adapt the query) and testability (since the Rx query can be much more easily unit-tested).
There is nothing "special" about Rx. Rx is just a library, not a language feature. If you wanted to, you could have built Rx yourself in a normal old C# project, it just happened that the smart people at Microsoft thought of it first. The code is open source now so you can just download it and see how it all works (admittedly it got a lot more complex in v2)
In your example, the Rx code will need to do the following:
Reflectively look for an event called "MouseMove" on the frm object
Create an observable sequence (IObservable<MouseEventArgs>) from the event
Ensure the safe semantics of the implicit IObservable contract e.g. that values are sequential, the subscriptions are thread safe etc..
Do the condition check
Subscribe to the sequence (safely)
Print to the console when a value is pushed.
In contrast, the non-rx code does the following:
Recieves a virtual call from a base class
does the condition check
Prints the value to the console.
So no reflection & no safety checks, but the same result. In practice the performance will be very fast for both so you are unlikely to see any performance difference.
With regards to Unit testing, I think any argument for or against is nonsense. We are talking about a MouseMove event, how are you going to unit test that? Putting all that Rx in your code base doesn't appear to pay for itself in my opinion (slower, more code, another framework for a dev to understand, etc...)

Categories