放置位置被占用时防止拖放

Preventing Drag & Drop when drop position is occupied

我开始尝试使用 ReactiveUI,并且一直在研究如何实现简单的拖放操作。我在一个 itemscontrol 周围拖动矩形,它有一个面板网格。我有基本的拖放功能,但我想阻止 如果网格单元格被占用,则下降,并在将鼠标拖到已占用的单元格上时更改鼠标光标。我有一个字典,我使用消息总线检索内容,null 或 MyObject,然后将结果发送回另一条消息。

 MessageBus.Current.Listen<Point>().Subscribe(gp =>
        {
            MessageBus.Current.SendMessage(SegmentMap.ContainsKey(gp) ? SegmentMap[gp] : null);
        });

现在我有了结果,但我不知道如何使用它来修改我的拖放 Observable 方法链,即代替

 mouseMove.TakeUntil(mouseLeftUp)

类似

 mouseMove.TakeUntil(mouseLeftUp && IsCellClear == true)

我正在使用 WPF 和 MVVM。这是我的主要观察结果:

    var dropGridPosition = mouseLeftDown.SelectMany(start => mouseMove.TakeUntil(mouseLeftUp),
                        (start, end) => new DropGridPosition(new Point {X = end.X - start.X, 
                                                                        Y = end.Y -start.Y}, start))
                                                                     .Where(p => !p.DropOffset.Equals(_offsetZero))
                                                                     .DistinctUntilChanged();

检查以确保您不能使用 Bind 而不是 MessageBus(或在需要时传递 Observable)。在 RxUI (ReactiveUI) 中的大多数情况下,MessageBus 通常是一个糟糕的抽象。

对于 TakeUntil,您可能希望将 MouseUp 事件和 WhenAnyValue() 结合到 AllCell 属性。

像这样:

var isCellNotClear = this.WhenAnyValue(x => x.CellValue).Select(x => x != null);
// CombineLatest will take the multiple observables, 
// and with a lambda convert them into Observable with the result from the lambda.
var isCellNotClearOrLeftButtonUp = isCellNotClear.CombineLatest(mouseLeftButtonUp,
   (isCell, isMouseUp) => isCell || isMouseUp);
mouseMove.TakeUntil(isCellNotClearOrLeftButtonUp);