Как справиться с перетаскиванием без нарушения принципов MVVM? - PullRequest
18 голосов
/ 06 мая 2011

В настоящее время у меня есть XAML

<TabControl  
    AllowDrop="True"
    PreviewDragOver="DragOver"
    PreviewDrop="Drop" />

Весь мой код перетаскивания существует внутри кода моего представления, а не внутри моей модели представления.

Как я могу справиться с перетаскиванием/ падение в моей ViewModel без добавления каких-либо зависимостей на View?

Ответы [ 4 ]

19 голосов
/ 07 мая 2011

Для этого есть библиотеки, такие как гонг и подобные фрагменты в различных статьях блога.

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

void ButtonClicked(object sender, EventArgs e)
{
    ((MyViewModel) this.DataContext).DoSomething();
}

Привязка команд может быть лучшим выбором, но логика определенно находится в модели представления. С чем-то вроде Drag and Drop, это более изменчиво, где вы хотите нарисовать линию. Вы можете использовать программный код для интерпретации Drag Args и при необходимости вызывать методы в модели представления.

12 голосов
/ 03 июня 2016

Вот код, который я написал, который позволяет вам перетаскивать файлы на элемент управления, не нарушая MVVM.Его можно легко изменить для передачи фактического объекта вместо файла.

/// <summary>
/// IFileDragDropTarget Interface
/// </summary>
public interface IFileDragDropTarget
{
    void OnFileDrop(string[] filepaths);
}

/// <summary>
/// FileDragDropHelper
/// </summary>
public class FileDragDropHelper
{
    public static bool GetIsFileDragDropEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsFileDragDropEnabledProperty);
    }

    public static void SetIsFileDragDropEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsFileDragDropEnabledProperty, value);
    }

    public static bool GetFileDragDropTarget(DependencyObject obj)
    {
        return (bool)obj.GetValue(FileDragDropTargetProperty);
    }

    public static void SetFileDragDropTarget(DependencyObject obj, bool value)
    {
        obj.SetValue(FileDragDropTargetProperty, value);
    }

    public static readonly DependencyProperty IsFileDragDropEnabledProperty =
            DependencyProperty.RegisterAttached("IsFileDragDropEnabled", typeof(bool), typeof(FileDragDropHelper), new PropertyMetadata(OnFileDragDropEnabled));

    public static readonly DependencyProperty FileDragDropTargetProperty =
            DependencyProperty.RegisterAttached("FileDragDropTarget", typeof(object), typeof(FileDragDropHelper), null);

    private static void OnFileDragDropEnabled(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue == e.OldValue) return;
        var control = d as Control;
        if (control != null) control.Drop += OnDrop;
    }

    private static void OnDrop(object _sender, DragEventArgs _dragEventArgs)
    {
        DependencyObject d = _sender as DependencyObject;
        if (d == null) return;
        Object target = d.GetValue(FileDragDropTargetProperty);
        IFileDragDropTarget fileTarget = target as IFileDragDropTarget;
        if (fileTarget != null)
        {
            if (_dragEventArgs.Data.GetDataPresent(DataFormats.FileDrop))
            {
                fileTarget.OnFileDrop((string[])_dragEventArgs.Data.GetData(DataFormats.FileDrop));
            }
        }
        else
        {
            throw new Exception("FileDragDropTarget object must be of type IFileDragDropTarget");
        }
    }
}

Использование:

<ScrollViewer AllowDrop="True" Background="Transparent" utility:FileDragDropHelper.IsFileDragDropEnabled="True" utility:FileDragDropHelper.FileDragDropTarget="{Binding}"/>

Убедитесь, что DataContext наследует от IFileDragDropTarget и реализует OnFileDrop.

public class MyDataContext : ViewModelBase, IFileDragDropTarget
{
    public void OnFileDrop(string[] filepaths)
    {
        //handle file drop in data context
    }
}
0 голосов
/ 22 апреля 2018

Это просто дополнительный ответ, который переносит ответ @ Аше на VB.NET для разработчиков на VB.

    Imports System.Windows

    Interface IFileDragDropTarget

        Sub OnFileDrop(ByVal filepaths As String())

    End Interface

  Public Class FileDragDropHelper

        Public Shared Function GetIsFileDragDropEnabled(ByVal obj As DependencyObject) As Boolean
            Return CBool(obj.GetValue(IsFileDragDropEnabledProperty))
        End Function

        Public Shared Sub SetIsFileDragDropEnabled(ByVal obj As DependencyObject, ByVal value As Boolean)
            obj.SetValue(IsFileDragDropEnabledProperty, value)
        End Sub

        Public Shared Function GetFileDragDropTarget(ByVal obj As DependencyObject) As Boolean
            Return CBool(obj.GetValue(FileDragDropTargetProperty))
        End Function

        Public Shared Sub SetFileDragDropTarget(ByVal obj As DependencyObject, ByVal value As Boolean)
            obj.SetValue(FileDragDropTargetProperty, value)
        End Sub

        Public Shared ReadOnly IsFileDragDropEnabledProperty As DependencyProperty = DependencyProperty.RegisterAttached("IsFileDragDropEnabled", GetType(Boolean), GetType(FileDragDropHelper), New PropertyMetadata(AddressOf OnFileDragDropEnabled))

        Public Shared ReadOnly FileDragDropTargetProperty As DependencyProperty = DependencyProperty.RegisterAttached("FileDragDropTarget", GetType(Object), GetType(FileDragDropHelper), Nothing)

        Shared WithEvents control As Windows.Controls.Control
        Private Shared Sub OnFileDragDropEnabled(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
            If e.NewValue = e.OldValue Then Return
            control = TryCast(d, Windows.Controls.Control)
            If control IsNot Nothing Then
                AddHandler control.Drop, AddressOf OnDrop
            End If
        End Sub

        Private Shared Sub OnDrop(ByVal _sender As Object, ByVal _dragEventArgs As DragEventArgs)
            Dim d As DependencyObject = TryCast(_sender, DependencyObject)
            If d Is Nothing Then Return
            Dim target As Object = d.GetValue(FileDragDropTargetProperty)
            Dim fileTarget As IFileDragDropTarget = TryCast(target, IFileDragDropTarget)
            If fileTarget IsNot Nothing Then
                If _dragEventArgs.Data.GetDataPresent(DataFormats.FileDrop) Then
                    fileTarget.OnFileDrop(CType(_dragEventArgs.Data.GetData(DataFormats.FileDrop), String()))
                End If
            Else
                Throw New Exception("FileDragDropTarget object must be of type IFileDragDropTarget")
            End If
        End Sub
    End Class
0 голосов
/ 16 июля 2011

Это также может вам помочь. Прикрепленная библиотека поведения команд позволяет вам преобразовывать любые события в команду, которая будет более точно соответствовать структуре MVVM.

http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/

Использовать это очень просто. И спас мой бекон много раз

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...