views:

59

answers:

1

I am trying to use a pair of Subject classes to fire away 2 sets of event sequences. The application is a drawing application, where one subject fires an onNext when the user clicks and the other subject fires an OnNext when the user doubleclicks. I have written GetClick & GetDoubleClick methods that return an observable for the above cases and seem to work fine. The problem in the code below is that if call onNext on the first subject to fire the click sequence, the double click observable never gets called. If I comment out the onNext call on the first subject the double click observable does get fired as expected. Can anyone take a look at the code below and their ideas/thoughts along? I have added comments to the problem line of code below

public static KeyValuePair<IObservable<MapPoint>, IObservable<PointCollection>> 
    DrawPointsDynamic(this Map map)
{
    PointCollection pc = new PointCollection();
    Subject<Point> ptSubject = new Subject<Point>();
    Subject<PointCollection> ptsSubject = new Subject<PointCollection>();

    IObservable<Point> ptObs = ptSubject.Hide();
    IObservable<PointCollection> ptsObs = ptsSubject.Hide();

    map.GetClick()
        .Subscribe(next =>
            {
                var p = map.ScreenToMap(next.EventArgs.GetPosition(map));
                ptSubject.OnNext(p); //If I leave this line in, the subscription to the doubleClick below does not get called. If comment it out, the subscription below does get called as expected;
                pc.Add(p);

            });

    map.GetDoubleClick()
        .Subscribe(next =>
        {
            ptsSubject.OnNext(pc);
            pc = new ESRI.ArcGIS.Client.Geometry.PointCollection();
        });

    KeyValuePair<IObservable<MapPoint>, IObservable<ESRI.ArcGIS.Client.Geometry.PointCollection>> obs =
        new KeyValuePair<IObservable<MapPoint>, IObservable<ESRI.ArcGIS.Client.Geometry.PointCollection>>
            (ptObs, ptsObs);

    return obs;
}

Also, I am not really sure what Hide() does. I am just using it since all the examples seem to have em. What does hiding the identity really mean?

+1  A: 

Rather than trying to fix the problem you have now, I'd suggest to rx-ify it a bit. First iteration is pretty straightforward:

public static KeyValuePair<IObservable<MapPoint>, IObservable<PointCollection>> 
    DrawPointsDynamic(this Map map) 
{
    var pc = new PointCollection();
    var ptSubject = map.GetClick().Select(next => map.ScreenToMap(next.EventArgs.GetPosition(map)).Publish();
    var ptsSubject = map.GetDoubleClick().Publish();

    ptSubject.Subscribe(pc.Add);
    ptsSubject.Subscribe(_ =>  pc = new PointCollection());

    ptSubject.Connect();
    ptsSubject.Connect();

    return new KeyValuePair<IObservable<MapPoint>, IObservable<PointCollection>>(ptObs, ptsObs);
}

Now, by looking at this I suspect what you really want though is this:

public static IObservable<PointCollection> DrawPointsDynamic(this Map map)
{
    var pcs = map.GetDoubleClick().Select(_ => new PointCollection()).Publish();
    var ps = map.GetClick().Select(next => map.ScreenToMap(next.EventArgs.GetPosition(map)));
    var ppcs = pcs.SelectMany(pc => ps.Select(p => { pc.Add(p); return pc; }).TakeUntil(pcs));

    var obs = pcs.Merge(ppcs);

    pcs.Connect();

    return obs;
}

This will return an observable that would produce PointCollection on click or double click with or without points in it.

PL