Тут на парах с поцонами дошли до Rx и я сел налабать для них простенький пример, что б была отправная точка для обсуждения. Времени до начала пары было немного, поэтому решил "рыбу" взять из интернетов. Чёрта-с-два! Оказалось, что пока я тут спал в берлоге, вышел Rx 2.0 (и даже 2.1 и 2.2) и куча тривиальных "brief examples" примеров, раскиданных по интертетам протухла. Например, уже не актуальны (не скомпилируются на Rx 2.0):
Поэтому пришлось править несколько больше.
Push-коллекцию из события WPF-компонентов теперь надо получать через функцию FromEventPattren (FromEvent тоже остался, но её сигнатура изменилась):
var mouseDownEvents = from e in Observable
.FromEventPattern
(
listener => listener.Invoke,
listener => Image.MouseDown += listener,
listener => Image.MouseDown -= listener
)
select e.EventArgs.GetPosition(Image);
Функция Until теперь называется TakeUntil:
var dragAndDrops =
from clickPosition in mouseDownEvents
from movePosition in mouseMoveEvents
.TakeUntil(mouseUpEvents.Merge(mouseLeaveEvents))
select new
{
X = movePosition.X - clickPosition.X,
Y = movePosition.Y - clickPosition.Y
};
Теперь нету Observable.Context: вместо этого надо звать у push-коллекции ObserveOn:
_unsubscribe = dragAndDrops.ObserveOn(SynchronizationContext.Current)
.Subscribe(newImagePosition =>
{
Canvas.SetLeft(Image, newImagePosition.X);
Canvas.SetTop(Image, newImagePosition.Y);
});
В плане корректности кода, тут эта штука не нужна, но лишний раз напоминает студентам, что надо задумываться о том, в какой нити будет вызван код.
В дополнение пару важных штук, на мой взгляд, сделал в примере:
- Отписка от событий. ИМХО, это анти-социальная саботажная деятельность - выкладывать в сеть примеры, где опущена очистка ресурсов. Ладно там продвинутые поцоны задумаются. А неопытные так и накопипастят, как есть, а потом Word у нас по пол минуты стартует, пароли утекают и пр. Утрирую, конечно :) Но идея, думаю, понятна.
- Пример, хоть и тривиальный, но почему-то нигде не доведён до конца: окромя нажатия, перемещения и отжатия мыши во всех примерах, которые видел, не было обработки выхода курсора за пределы таскаемого объекта (доехали до границы окна, очень быстро метнулись и пр.).
Выжимка кода тут:
http://pastebin.com/ygmGrJjNПолноценный проект с примером тут:
https://www.dropbox.com/s/xto1r0yvw32lkfj/RxPrimitiveExample.zip?dl=0