私はStevePsaltisのアイデアを機能させることに挑戦しました。しばらく時間がかかりました-カスタム依存関係プロパティは間違えやすいです。SetXXX
副作用を配置するのに間違った場所であるように私には思えます-WPFはそこに行く必要はなく、直接行くことができますDependencyObject.SetValue
が、PropertyChangedCallback
常に呼び出されます。
したがって、カスタムアタッチされたプロパティのコードは次のように完成し、機能します。
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
私にはより良いと思われるコマンドにスルースルーします。ファイルなど、コマンド内のあらゆるものをクエリできます。しかし、それは現在の好みであり、答えの本質的な特徴ではありません。