Reputation: 37045
Suppose I am building an image editor using Rx.Net. The user can manipulate the canvas using the mouse. The manipulation that is applied depends on the currently selected tool. For example, there might be a "draw" tool and an "erase" tool. Only one tool can be selected at a time.
I have three streams; one for mouse events; one for commands issued by clicking the mouse; and another for tool selections:
IObservable<ITool> toolSelection;
IObservalbe<MouseState> mouse;
IObservable<ICommand> commands;
The commands
stream depends on the other two: commands are issued when the user clicks the mouse and the command generated depends on the last selected tool. Note that a command should not be issued when the user changes tool, only when they click the mouse.
Now, I could store the last selected tool in a variable like this:
var selectedTool = defaultTool;
toolSelection.Subscribe(x => selectedTool = x);
I can use selectedTool
to build the commands
stream:
var commands = mouse.Select(x => selectedTool.CreateCommand(x));
However, this doesn't seem like the "reactive" way of doing things. Can I achieve this same logic using stream compositions?
I have looked at CombineLatest
but it causes unwanted events to be generated when the user switches tool. I only want commands to be issued when the user clicks.
Upvotes: 5
Views: 912
Reputation: 117027
It sounds like you need .Switch()
.
Try this code:
IObservable<ICommand> commands =
toolSelection
.Select(t => mouse.Select(m => t.CreateCommand(m)))
.Switch();
The extension method .Switch()
takes, in this case, an IObservable<IObservable<ICommand>>
and turns it into an IObservable<ICommand>
by taking the latest observable produced by the outer observable and only producing values from it and disposing of previous ones.
Or, in more English terms, whenever the user clicks on a new tool you get a stream of mouse commands built using only the latest tool in one nice query.
Upvotes: 4