How do I convert a ListView SelectedItem into an IObservable? - c#

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)));
}

Related

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

Rx with button tap and hold event in Windows Phone 8

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.

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...)

How to automatically generating an extension method library of WPF Event -> IObservable

I almost exclusively use Reactive Extensions in my C# WPF apps these days. Adding and removing event handlers is an anti pattern and I'm completely jealous of the fact that F# events implement IObservable.
To help C# developers the RX folks provide the below method ( and some others of varying type safeness )
public static
IObservable<EventPattern<TEventArgs>>
FromEventPattern<TDelegate, TEventArgs>
( Action<TDelegate> addHandler
, Action<TDelegate> removeHandler
)
where TEventArgs : EventArgs
http://msdn.microsoft.com/en-us/library/hh211731(v=vs.103).aspx
I would use it like so
var movingEvents = Observable.FromEventPattern<MouseEventHandler,
MouseEventArgs>(h => this.MouseMove += h, h => this.MouseMove -= h);
However this is tedious. What I'd like to be able to do is
var movingEvents = h.MouseMoveObserver();
and be done with it. Such an extension method would look like
IObservable<MouseEventArgs> MouseMoveObserver(this Canvas This){
return Observable.FromEventPattern<MouseEventHandler,
MouseEventArgs>(h => This.MouseMove += h, h => This.MouseMove -= h);
}
It's not rocket science and I've been considering setting up a library where I add these extension methods one at a time as I need them. However I am sure some smart cookie could write a T4 template that processes all the controls in the WPF library via reflection and generates all the extension methods I would ever need. My question is ...
Has anybody written such a code generator to map events to observables as above and if not would someone have any suggestions on how to do this? I'm not so good with regards to .Net reflection but some seed code might get me started.
To get all the types deriving from FrameworkElement, you could use
var typesToDo = from t in Assembly.GetAssembly(typeof(FrameworkElement)).GetTypes()
where t.IsSubclassOf(typeof(FrameworkElement))
&& t.IsPublic
&& t.GetEvents().Any()
select t;
and then you can use type.GetEvents() to get the events of each type. The EventInfo you get back will let you look at things like name, type, arguments etc.
You need to do a bit of extra work to cope with generic events, but it's not a huge amount.
I've put an example program up on GitHub along with an example of the output.
There is a risk that some of the output doesn't work properly, I haven't tried them all :) I did make sure they all build, and that at least some of them work correctly.

bind linq expression

I have a ListView and ObservableCollection in my wpf application.
I want to bind linq expression to ListView:
lv_Results.DataContext = store.Where(x => x.PR > 5).ToList();
tempStore = new M1Store()
{
SiteName = siteName,
Date = date,
url = IndexedPage,
TCY = YandexTCY.GetYandexTCY(IndexedPage),
PR = Pagerank.GetPR(IndexedPage)
};
store.Add(tempStore);
But when i add new elements to store collection, lv_Results doesnt updates.
How can i update ListView?
Your problem is that you want the "Where" condition to be evaluated continuously on all items added to the "store" collection. The built-in LINQ "Where" operator is not designed to do that. Rather, when it is enumerated by the ListView it scans your collection exactly once then ignores it from then on.
Check out Continuous LINQ. It is designed to do exactly what you are looking for, and can be used almost as a drop-in replacement for standard LINQ queries.
Limitations of the built-in LINQ implementation
The built-in LINQ extension methods have a fundamental limitation in that the collections they produce don't support INotifyPropertyChanged. So no matter how much the underlying data changes, the client will never receive notification that the collection has changed and hence will never refresh its display of the data.
User jrista points out in the comments that the built-in LINQ methods do actually produce up-to-date data if re-enumerated. While true, this has no practical effect. No WinForms or WPF control contains code to periodically re-enumerate its data source. The reasons for not doing so are, of course, obvious: It would be incredibly wasteful. If you re-enumerate 10 times per second and it takes 10ms to re-enumerate and scan for changes you will use up 10% of your CPU for just one control!
Put your LINQ results into an ObservableCollection. WPF and Silverlight databinding require that collections raise change notifications, and ObservableCollection does that for you. Otherwise you'd have to implement it yourself, which is more of a pain and completely unnecessary.
The results from the LINQ expression are being fed into a new List(of T) which does not raise PropertyChanged or CollectionChanged events.
The easiest way to make it work is to retrieve the results you want, then populate an ObservableCollection(of T) with the results you want to display. As that ObservableCollection gets added to, the new items will appear in the ListView.
Add a .ToList() to your code, LINQ evaluates lazy, so it brings results only when needed, .ToList() is a greedy operator and forces an evaluation.
[edit]
Sorry, missunterstood your first version of the question :)
Here's my solution:
ObservableCollection<M1Store> l = store.Where(x => x.PR > 5);
lv_Results.DataContext = l;
Thats simply all, in all following steps, change the Observable collection l:
List<M1Store> otherList = GetFromAnywhere();
otherList.ForEach(e => l.Add(e));
Here the internals of the Observable Collection will Update the listView in the UI.

Categories