问题:我有一个WPF项目,我想使用MVVM-pattern。我想使用ICommand来抽象事件。但问题是我无法恢复我的EventArgs,因为它是"背后"命令(例如OnDrop路径)。
信息: ICommand用于抽象事件,因为命令可以多次使用。命令更集中于背后的逻辑(MVVM-Pattern)。
我正在使用System.Windows.Interactivity
和中继命令。
RelayCommand.cs
public class RelayCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public RelayCommand(Predicate<object> canExecute, Action<object> execute)
{
_canExecute = canExecute;
_execute = execute;
}
public bool CanExecute(object parameter)
{
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
}
我尝试了以下解决方案:
1。具有依赖对象的行为
我无法取回我的Event Args。
2。具有关联对象和OnAttached的行为
https://wpftutorial.net/Behaviors.html
我遇到了同样的问题,无法取回我的EventArgs。
3。方法绑定
MainView.xaml
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
<i:EventTrigger EventName="Drop">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="OnRectangleDrop"/>
</i:EventTrigger>
这对我有用,但是这里的问题是,在XAML或代码中,WPF不会更改名称,方法名称已更改。
问题: 如何在不使用框架或库的情况下以有效的方式让我的 EventArgs 退出我的命令?
答案 0 :(得分:1)
从事件开始。一旦获得了与事件一起使用的代码,它通常可以重构为可重用的附加行为。
E.g。这是一个分配命令,它接收来自拖放项目的传递字符串。
public static partial class Behaviors
{
public static ICommand GetDrop(DependencyObject obj) => (ICommand)obj.GetValue(DropProperty);
public static void SetDrop(DependencyObject obj, ICommand value) => obj.SetValue(DropProperty, value);
public static readonly DependencyProperty DropProperty =
DependencyProperty.RegisterAttached("Drop", typeof(ICommand), typeof(Behaviors), new PropertyMetadata(null, (d, e) =>
{
var element = d as UIElement;
element.Drop += (s, a) =>
{
if (a.Data.GetDataPresent(DataFormats.StringFormat))
{
var command = (ICommand)e.NewValue;
var data = (string)a.Data.GetData(DataFormats.StringFormat);
if (command.CanExecute(data))
command.Execute(data);
}
};
}));
}
我想它会与您的文件路径一起使用,只需在绑定中使用它:
<SomeUIElement AllowDrop="True"
Background="Transparent"
local:Behaviors.Drop="{Binding SomeCommand}" />
,其中
SomeCommand = new RelayCommand(o => true, o => MessageBox.Show($"File {o}"));
另一点是开始拖动。您还可以使用附加行为,例如传递文本的一个(可以是绑定):
public static partial class Behaviors
{
public static string GetDrag(DependencyObject obj) => (string)obj.GetValue(DragProperty);
public static void SetDrag(DependencyObject obj, string value) => obj.SetValue(DragProperty, value);
public static readonly DependencyProperty DragProperty =
DependencyProperty.RegisterAttached("Drag", typeof(string), typeof(Behaviors), new PropertyMetadata(null, (d, e) =>
{
var element = d as UIElement;
element.MouseMove += (s, a) =>
{
if (a.LeftButton == MouseButtonState.Pressed)
DragDrop.DoDragDrop(element, e.NewValue, DragDropEffects.Copy);
};
}));
}
用法是:
<Something local:Behaviors.Drag="text" ... />
答案 1 :(得分:0)
如何在不使用框架或库的情况下以有效的方式让我的EventArgs退出我的命令?
System.Windows.Interactivity.dll
和Microsoft.Expressions.Interactions.dll
中没有类将EventArgs作为命令参数传递给命令。
MvvmLight中有一个EventToCommand
课程,您可以使用http://blog.galasoft.ch/posts/2014/01/using-the-eventargsconverter-in-mvvm-light-and-why-is-there-no-eventtocommand-in-the-windows-8-1-version/。
另一种选择是实现自己的自定义TriggerAction<FrameworkElement>
。您可以查看MvvmLight实现:https://github.com/paulcbetts/mvvmlight/blob/dce4e748c538ed4e5f5a0ebbfee0f54856f52dc6/V3/GalaSoft.MvvmLight/GalaSoft.MvvmLight.Extras%20(NET35)/Command/EventToCommand.cs
或者您可以在视图的代码隐藏中处理Drop
事件,只需按照@Evk的建议从事件处理程序调用命令:
private void OnDrop(object sender, DragEventArgs e)
{
var viewModel = DataContext as YourViewModelType;
if (viewModel != null)
viewModel.OnRectangleDrop.Execute(e);
}
当然,您可以从DragEventArgs
中提取任何值,并将此值传递给命令。