Перетащите в MVVM с ScatterView - PullRequest
6 голосов
/ 23 июня 2009

Я пытаюсь реализовать функцию перетаскивания в приложении Surface, построенном с использованием шаблона MVVM. Я изо всех сил пытаюсь найти способ реализовать это, придерживаясь шаблона MVVM. Хотя я пытаюсь сделать это в приложении Surface, я думаю, что решение достаточно общее, чтобы применять его и к WPF.

Я пытаюсь создать следующую функциональность:

  • Пользователь связывается с FrameworkElement в ScatterViewItem, чтобы начать операцию перетаскивания (определенная часть ScatterViewItem инициирует функцию перетаскивания)
  • Когда начинается операция перетаскивания, создается копия этого ScatterViewItem, которая накладывается на исходный элемент ScatterViewItem, - это копия, которую пользователь перетаскивает и, в конечном итоге, удаляет
  • Пользователь может перетащить элемент в другой ScatterViewItem (помещенный в отдельный ScatterView)

Общее взаимодействие очень похоже на приложение ShoppingCart, предоставляемое в Surface SDK, за исключением того, что исходные объекты содержатся в ScatterView, а не в ListBox.

Я не уверен, как поступить, чтобы обеспечить надлежащую связь между моими ViewModels для обеспечения этой функциональности. Основная проблема, с которой я столкнулся, - это репликация ScatterViewItem, когда пользователь обращается к FrameworkElement.

Ответы [ 2 ]

4 голосов
/ 03 сентября 2009

Вы можете использовать прикрепленное свойство. Создайте вложенное свойство и в методе setproperty привяжите к удаленному событию:


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

Затем вы можете привязать команду в вашей модели представления к соответствующему элементу управления в представлении. Очевидно, что вы можете захотеть, чтобы ваше присоединенное свойство применялось к вашему конкретному типу элемента управления, а не к списку.

Надеюсь, это поможет.

2 голосов
/ 28 января 2011

Я попытался реализовать идею Стива Псалтиса. Потребовалось некоторое время - пользовательские свойства зависимостей легко ошибаются. Мне кажется, что SetXXX - это не то место, где можно поместить ваши побочные эффекты - WPF не обязательно должен идти туда, он может перейти прямо к DependencyObject.SetValue, но всегда будет вызываться PropertyChangedCallback 1004 *

Итак, вот полный и работающий код для пользовательского присоединенного свойства:

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 команде, которая кажется мне лучше - вы можете запросить ее для файлов или чего-либо еще в команде. Но это всего лишь текущее предпочтение, а не существенная особенность ответа.

...