我已经实现了一个WPF小应用程序,可以将动物从商店拖到我的谷仓中。 ;-)

我正在使用:


MVVMlight及其EventToCommand行为
动物是在Border上监听的简单MouseDown
谷仓是绑定到ViewModel的ItemsControlObservableCollection。它监听3个事件:

DragEnter(向ObservableCollection中添加虚拟动物以预览动物在谷仓中的放置位置)
DragLeave(如果没有将动物掉落,则将其删除)
Drop(将动物放置在谷仓中的指定位置)。



抱歉。我没有上传图像的声誉。因此,我尝试了一些ascii艺术(尝试将驴图像拖入谷仓):

Shop   | Barn
-------------------------
Mouse  | [Mouse] [Dog]
Cat    | [.]
Dog    |  ^
Donkey-|--|


这是问题所在:

如果我将动物拖入谷仓的指定空间(预览模型):


DragLeave删除虚拟项目,并立即
将触发DragEnter重新绘制虚拟物品。转到步骤1。


无限循环。闪烁开始并开始运行!

有谁知道一个不错的解决方法?

所以这是我的ViewModel的代码:

private string _dummy;
public ObservableCollection<string> Animals { get; private set; }

private void StartDrag(FrameworkElement element)
{
    var animal = element.DataContext as string;
    if (animal == null) return;
    System.Windows.DragDrop.DoDragDrop(element, animal, DragDropEffects.Copy);
}

private void PreviewDrop(DragEventArgs args)
{
    if (args.Data.GetDataPresent(typeof (string)))
        AddDummy();
}

private void StopDrop(DragEventArgs args)
{
    RemoveDummy();
}

private void Drop(DragEventArgs args)
{
    var animal = args.Data.GetData(typeof (string)) as string;
    if (animal == null) return;

    RemoveDummy();
    Animals.Add(animal);
}

private void RemoveDummy()
{
    if (_dummy == null) return;
    Animals.Remove(_dummy);
    _dummy = null;
}

private void AddDummy()
{
    if (_dummy != null) return;
    _dummy = ".";
    Animals.Add(_dummy);
}


谢谢你的帮助

马塞尔

最佳答案

好,我知道了。 IsHitTestVisible达到目的!这是2个解决方案:

第一种方法,快速方法:
只需将谷仓中的所有动物(通过将目标ItemTemplate中的ItemsControl修改为)设置为IsHitTestVisible="False"

<ItemsControl.ItemTemplate>
    <DataTemplate DataType="{x:Type system:String}">
        <Border Background="Gray" IsHitTestVisible="False">
            <TextBlock Text="{Binding}" Foreground="White" />
        </Border>
    </DataTemplate>
</ItemsControl.ItemTemplate>


因此,每个项目仍然可见,但是这些项目或ItemsControl均不会触发任何事件。可是等等!如果我想通过将新的动物拖到旧的动物上来替换动物,该怎么办?我至少需要一个适当的Drop事件?

第二种方法,更好的方法:
我仅将IsHitTestVisible="False"设置为虚拟动物(这里我将字符串内容与"."进行比较以检查它是否是虚拟动物)。

<ItemsControl.ItemTemplate>
    <DataTemplate DataType="{x:Type system:String}">
        <Border Name="AnimalPlace" Background="Gray">
            <TextBlock Text="{Binding}" Foreground="White" />
        </Border>
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding}" Value=".">
                <Setter TargetName="AnimalPlace" Property="IsHitTestVisible" Value="False" />
            </DataTrigger>
        </DataTemplate.Triggers>
    </DataTemplate>
</ItemsControl.ItemTemplate>


最后一种方法适用于MVVM方面,非常适合我的需求。更不用说它可以轻松地适应更复杂的对象(比表示动物的字符串更复杂)。

我现在很开心 :-)

10-06 09:06