Я попытался реализовать идею Стива Псалтиса. Потребовалось некоторое время - пользовательские свойства зависимостей легко ошибаются. Мне кажется, что SetXXX
- это не то место, где можно поместить ваши побочные эффекты - WPF не обязательно должен идти туда, он может перейти прямо к DependencyObject.SetValue
, но всегда будет вызываться PropertyChangedCallback
1004 *
Итак, вот полный и работающий код для пользовательского присоединенного свойства:
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
команде, которая кажется мне лучше - вы можете запросить ее для файлов или чего-либо еще в команде. Но это всего лишь текущее предпочтение, а не существенная особенность ответа.