3

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

我在用着:

  • MVVMlight 及其EventToCommand行为
  • 动物是一个简单的BorderMouseDown
  • 谷仓ItemsControl绑定到ObservableCollectionViewModel 的一个。它监听 3 个事件:
    • DragEnter(将虚拟动物添加ObservableCollection到预览动物在谷仓中的位置)
    • DragLeave(如果动物没有掉落,则移除虚拟动物)
    • Drop(将动物放在谷仓的指定位置)。

对不起。我没有上传图片的声誉。所以我尝试了一些 ascii 艺术(尝试将驴拖入谷仓的图像):

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

这是问题所在:

如果我将动物拖入谷仓到它的指定空间(预览假人):

  1. DragLeave删除虚拟项目并立即
  2. 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);
}

谢谢你的帮助

马塞尔

4

2 回答 2

3

好,我知道了。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 方面,完全符合我的需求。更不用说它可以很容易地适应更复杂的对象(比表示动物的字符串更复杂)。

我现在很开心 :-)

于 2013-11-12T07:55:25.587 回答
0

简单的解决方案,您可能只需要使用标志来控制DragLeaveDragEnter代码执行。检查这里以了解事件的顺序

于 2013-11-11T17:59:16.567 回答