在没有太多WPF经验的情况下在MVVM中实现拖拽,可以参考5个步骤;我将概述这些...
第 1 步:附加行为
为您的项目添加一个名为 Behaviours 的新类。它应该看起来像这样......
public static class Behaviours
{
#region DandBehaviour
public static readonly DependencyProperty DandBehaviourProperty =
DependencyProperty.RegisterAttached("DandBehaviour", typeof(ICommand), typeof(Behaviours),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.None,
OnDandBehaviourChanged));
public static ICommand GetDandBehaviour(DependencyObject d)
{
return (ICommand)d.GetValue(DandBehaviourProperty);
}
public static void SetDandBehaviour(DependencyObject d, ICommand value)
{
d.SetValue(DandBehaviourProperty, value);
}
private static void OnDandBehaviourChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Grid g = d as Grid;
if (g != null)
{
g.Drop += (s, a) =>
{
ICommand iCommand = GetDandBehaviour(d);
if (iCommand != null)
{
if (iCommand.CanExecute(a.Data))
{
iCommand.Execute(a.Data);
}
}
};
}
else
{
throw new ApplicationException("Non grid");
}
}
#endregion
}
这个类实现了一个附加的依赖属性,可以从你的 Xaml 和你的视图模型中访问。它挂钩“Drop”事件并在其上调用命令。
第 2 步:检测 Xaml
在此步骤中,您需要将名称空间添加到 Xaml,以便它可以找到步骤 1 中的行为类。它看起来像这样...
xmlns:b="clr-namespace:DdMvvm"
此语句将别名“b”分配给行为。然后你告诉 WPF 根窗口接受 drop...
AllowDrop="true"
然后您可以将行为添加到您的逻辑树中......
<Grid AllowDrop="True" b:Behaviours.DandBehaviour="{Binding DandCommand}">
<DockPanel Background="Bisque" AllowDrop="True"/>
</Grid>
第 3 步:添加命令支持
从http://msdn.microsoft.com/en-us/magazine/dd419663.aspx 下载 Josh Smith 的“中继命令”为了完整起见,这里给出...
public class RelayCommand : ICommand
{ //http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter)
{
_execute(parameter);
}
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;
}
第 4 步:编写视图模型
一个视图模型看起来像这样......
public class ViewModel : INotifyPropertyChanged
{
public ICommand DandCommand { get; set; }
public ViewModel()
{
DandCommand = new RelayCommand(ExecuteDandCommand, CanExecuteDandCommand);
}
private void ExecuteDandCommand(object obj)
{
if (obj != null)
{
IDataObject ido = obj as IDataObject;
if (ido != null)
{
var fileDrop = ido.GetData(DataFormats.FileDrop, true);
var filesOrDirectories = fileDrop as String[];
if (filesOrDirectories != null && filesOrDirectories.Length > 0)
{
foreach (string fullPath in filesOrDirectories)
{
if (Directory.Exists(fullPath))
{
Console.WriteLine(@"{0} is a directory", fullPath);
}
else if (File.Exists(fullPath))
{
Console.WriteLine(@"{0} is a file", fullPath);
}
else
{
Console.WriteLine(@"{0} is not a file and not a directory", fullPath);
}
}
}
}
}
}
private bool CanExecuteDandCommand(object obj)
{
return true;
}
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string name)
{
var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
此 VM 实现了一个命令(称为 DandCommand),该命令将被附加行为触发(还记得第 1 步吗?)。 VM 的“多汁部分”是取消引用拖放有效负载的位。在这个特定的 VM 中,代码取消引用数据并确定它是文件还是目录。然后它将诊断信息打印到控制台。您可以更改此部分以加载图像、互联网链接或任何可以删除的内容。
第 5 步:连接数据上下文
这是由不同的开发人员以不同的方式完成的(对于工业应用程序,很多人喜欢使用 Prism 和 Unity,但对于这篇文章的简单操作方法来说,这并不重要)。最直接的方法是将您的视图更改为如下所示...
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
此代码将窗口的数据上下文设置为您的 VM,以便可以进行绑定。
这些步骤为您提供了 MVVM 和拖放操作的良好起点,并让整个工作正常进行。将 MVVM 用于这些事情的最大回报是您获得的干净分离和划分。即,可以对 VM 进行单元测试,而无需实例化 WPF 绑定引擎。