6

MVVMパターンを使用して構築されたSurfaceアプリケーションにドラッグアンドドロップ機能を実装しようとしています。MVVMパターンを守りながら、これを実装する手段を考え出すのに苦労しています。私はSurfaceアプリケーション内でこれを実行しようとしていますが、ソリューションはWPFにも適用できるほど一般的だと思います。

次の機能を作成しようとしています。

  • ユーザーがScatterViewItem内のFrameworkElementに接続して、ドラッグ操作を開始します(ScatterViewItemの特定の部分がドラッグ/ドロップ機能を開始します)
  • ドラッグ操作が開始されると、そのScatterViewItemのコピーが作成され、元のScatterViewItemに適用されます。このコピーは、ユーザーがドラッグして最終的にドロップするものです。
  • ユーザーは、アイテムを別のScatterViewItem(別のScatterViewに配置)にドロップできます。

全体的な相互作用は、ソースオブジェクトがListBoxではなくScatterView内に含まれていることを除いて、SurfaceSDKで提供されているShoppingCartアプリケーションと非常によく似ています。

この機能を提供するためにViewModel間の適切な通信を有効にするために、どのように進めるかがわかりません。私が遭遇した主な問題は、ユーザーがFrameworkElementに連絡したときにScatterViewItemを複製することです。

4

2 に答える 2

4

You could use an attached property. Create an attached property and in the setproperty method bind to the droped event :


public static void SetDropCommand(ListView source, ICommand command)
        {
            source.Drop += (sender, args) =>
                               {
                                   var data = args.Data.GetData("FileDrop");
                                   command.Execute(data);
                               };
        }

Then you can bind a command in your view model to the relevant control on the view. Obviously you may want to make your attached property apply to your specific control type rather than a listview.

Hope that helps.

于 2009-09-03T19:52:12.423 に答える
2

私はStevePsaltisのアイデアを機能させることに挑戦しました。しばらく時間がかかりました-カスタム依存関係プロパティは間違えやすいです。SetXXX副作用を配置するのに間違った場所であるように私には思えます-WPFはそこに行く必要はなく、直接行くことができますDependencyObject.SetValueが、PropertyChangedCallback常に呼び出されます。

したがって、カスタムアタッチされたプロパティのコードは次のように完成し、機能します。

using System.Windows;
using System.Windows.Input;

namespace WpfApplication1
{
    public static class PropertyHelper
    {
        public static readonly DependencyProperty DropCommandProperty = DependencyProperty.RegisterAttached(
            "DropCommand",
            typeof(ICommand),
            typeof(PropertyHelper),
            new PropertyMetadata(null, OnDropCommandChange));

        public static void SetDropCommand(DependencyObject source, ICommand value)
        {
            source.SetValue(DropCommandProperty, value);
        }

        public static ICommand GetDropCommand(DependencyObject source)
        {
            return (ICommand)source.GetValue(DropCommandProperty);
        }

        private static void OnDropCommandChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ICommand command = e.NewValue as ICommand;
            UIElement uiElement = d as UIElement;
            if (command != null && uiElement != null)
            {
                uiElement.Drop += (sender, args) => command.Execute(args.Data);
            }

            // todo: if e.OldValue is not null, detatch the handler that references it
        }
    }
}

これを使用するXAMLマークアップでは、次のように実行できます。

xmlns:local="clr-namespace:WpfApplication1"
...
<Button Content="Drop here" Padding="12" AllowDrop="True"
   local:PropertyHelper.DropCommand="{Binding DropCommand}" />

..残りは、ViewModel、バインディング、およびコマンドが正しいことを確認するだけです。

このバージョンは、IDataObject私にはより良いと思われるコマンドにスルースルーします。ファイルなど、コマンド内のあらゆるものをクエリできます。しかし、それは現在の好みであり、答えの本質的な特徴ではありません。

于 2011-01-28T16:03:27.940 に答える