所以我之前看过这个链接:
这个类对于Files是完美无缺的,但它不支持目录等,有没有人知道我怎么能改变它来支持它,我没有pinvoke高手。我已经尝试了一百万种不同的东西,重写一些代码,将我的drop source文件复制和目录创建到TEMP目录并尝试触发FileDrop,但这会完全锁定应用程序。
这让我相信必须有更好的方法来启用目录结构创建。
答案 0 :(得分:0)
拖放操作的主要部分是DragDrop.DoDragDrop
方法。来自MSDN上的DragDrop.DoDragDrop
Method页:
public static DragDropEffects DoDragDrop(
DependencyObject dragSource,
Object data,
DragDropEffects allowedEffects
)
特别感兴趣的是data
参数:
包含被拖动数据的数据对象。
请注意此参数的类型为Object
,因此完全取决于你您在操作中使用的对象。现在我不确定你从链接到的页面找到了什么代码,但是如果我试图拖放文件和文件夹,我就不需要特殊的类来为我做了。
最简单的方法是只传递文件和/或文件夹路径而不是实际数据。删除数据的控件可以使用文件路径访问数据,就像拖动源一样容易。您应该能够从代码中找到DragDrop.DoDragDrop
方法,并轻松调整该代码。
如果您想以正确的方式执行拖放操作,那么我建议您查看MSDN上的Drag and Drop Overview页面。它完全解释了要做什么,并提供了几个代码示例。
答案 1 :(得分:0)
要在没有WPF经验的情况下实现MVVM中的拖放,可以参考5个步骤;我将概述这些......
第1步:附加行为
在项目中添加一个名为Behaviors的新类。看起来应该是这样......
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和View Model中访问它。它挂钩“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的'Relay Command'为了完整起见,这里给出了......
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绑定引擎。