Тривиальный Drag'n'Drop внутри окна на Rx для .NET

Mar 08, 2015 19:18

Тут на парах с поцонами дошли до 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

rx, csharp, .net

Previous post Next post
Up