2011-05-06 8 views
13

Actualmente tengo en mi XAML¿Cómo manejar arrastrar/soltar sin violar los principios de MVVM?

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

Toda mi arrastrar/soltar existe código en el código subyacente de mi punto de vista, en lugar de dentro de mi modelo de vista.

¿Cómo puedo manejar arrastrar/soltar en mi ViewModel sin agregar ninguna dependencia en la vista?

Respuesta

18

Hay bibliotecas para esto como gong y fragmentos similares en varios artículos de blog.

Sin embargo, no debe preocuparse demasiado por no tener código oculto. Por ejemplo, esto sigue siendo MVVM en mi libro:

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

Un comando vinculante podría ser una mejor opción, pero la lógica es, sin duda en el modelo de vista. Con algo así como Arrastrar y soltar, es más variable donde quieras dibujar la línea. Puede tener código subyacente para interpretar los Args Arg y los métodos de llamada en el modelo de vista cuando sea apropiado.

+1

es una buena solución si tiene un modelo pequeño y estático, pero no si necesita un acoplamiento flojo y utiliza la inyección de dependencia. – bitman

3

Aquí hay un código que escribí que le permite arrastrar y soltar archivos en un control sin violar MVVM. Se podría modificar fácilmente para pasar el objeto real en lugar de un archivo.

/// <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"); 
     } 
    } 
} 

Uso:

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

Asegúrese de que el DataContext hereda de IFileDragDropTarget e implementa el OnFileDrop.

public class MyDataContext : ViewModelBase, IFileDragDropTarget 
{ 
    public void OnFileDrop(string[] filepaths) 
    { 
     //handle file drop in data context 
    } 
} 
Cuestiones relacionadas