3

動物を店から納屋にドラッグする小さな WPF アプリを実装しました。;-)

私は使用しています:

  • MVVMlight とそのEventToCommand動作
  • 動物は単純なBorderリスニングですMouseDown
  • 納屋はViewModel の にItemsControlバインドされています。ObservableCollection3 つのイベントをリッスンします。
    • DragEnter(ダミー動物を に追加してObservableCollection、動物が納屋のどこに配置されているかをプレビューします)
    • DragLeave(動物がドロップされていない場合は、ダミーの動物を削除します)
    • Drop(動物を納屋の指定された場所に置きます)。

ごめん。画像をアップロードするという評判はありません。だから私はいくつかのアスキーアートを試します(ロバを納屋にドラッグするイメージを試してみてください):

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イベントが必要ですか?

2 番目のアプローチ、より良い方法:ダミーの動物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

DragLeave簡単な解決策です。フラグを使用してDragEnterコードの実行を制御するだけでよい場合があります。イベントの順序を理解するには、ここを確認してください

于 2013-11-11T17:59:16.567 に答える