我已经实现了一个WPF小应用程序,可以将动物从商店拖到我的谷仓中。 ;-)
我正在使用:
MVVMlight及其EventToCommand
行为
动物是在Border
上监听的简单MouseDown
谷仓是绑定到ViewModel的ItemsControl
的ObservableCollection
。它监听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方面,非常适合我的需求。更不用说它可以轻松地适应更复杂的对象(比表示动物的字符串更复杂)。
我现在很开心 :-)