有时我们多次使用复杂的方式,我们忘记了完成任务的最简单方法。
我知道如何进行命令绑定,但我总是使用相同的方法。
创建一个实现ICommand接口的类,并从视图模型中创建该类的新实例,绑定就像魅力一样。
这是我用于命令绑定的代码
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
testCommand = new MeCommand(processor);
}
ICommand testCommand;
public ICommand test
{
get { return testCommand; }
}
public void processor()
{
MessageBox.Show("hello world");
}
}
public class MeCommand : ICommand
{
public delegate void ExecuteMethod();
private ExecuteMethod meth;
public MeCommand(ExecuteMethod exec)
{
meth = exec;
}
public bool CanExecute(object parameter)
{
return false;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
meth();
}
}
但我想知道这样做的基本方法,没有第三方dll没有新的类创建。使用单个类执行此简单命令绑定。实际的类从ICommand接口实现并完成工作。
答案 0 :(得分:15)
Prism已提供Microsoft.Practices.Prism.Commands.DelegateCommand
我不确定它是否被视为第三方。至少它是官方的,并在MSDN上有记录。
一些本机内置命令,如copy,paste实现ICommand接口。 恕我直言打开(扩展)/关闭(改变)原则。这样我们就可以实现自己的命令。
WPF命令记录here,摘录......
WPF提供了一组预定义命令。如Cut,BrowseBack和 BrowseForward,Play,Stop和Pause。
如果命令库类中的命令不符合您的需求, 然后你可以创建自己的命令。有两种方法可以创建 自定义命令。首先是从头开始实施 ICommand接口。另一种方式,更常见的方法, 是创建RoutedCommand或RoutedUICommand。
我在开始时尝试过RoutedCommand模型,最终实现了ICommand。
示例XAML绑定
<CommandBinding Command="{x:Static custom:Window1.CustomRoutedCommand}"
Executed="ExecutedCustomCommand"
CanExecute="CanExecuteCustomCommand" />
RoutedCommand与RoutedEvent没有什么不同。这似乎是一个更好的按钮'Clicked'事件处理程序。它的目的是:将应用程序逻辑与View分开但需要一些附加DependencyProperty或代码隐藏。
就我个人而言,只要实现我的ICommand,我感觉更舒服。
答案 1 :(得分:3)
我倾向于使用内置了RelayCommand的MVVM灯架。
您将ICommand属性添加到视图模型,然后为其分配relaycommand: -
ICommand ClickMeCommand {get;set;}
private void InitCommands()
{
ClickMeCommand = new RelayCommand(()=>HasBeenClicked=true);
//or
ClickMeCommand = new RelayCommand(ClickMeEvent);
}
public void ClickMeEvent()
{
HasBeenClicked=true;
}
在xaml中你只需使用普通绑定: -
<Button Content='Push me' Command='{Binding ClickMeCommand}' />
答案 2 :(得分:2)
如果您不想创建新课程,请使用routed命令。这是一个小片段。我已经创建了一个路由命令作为Save并将其绑定到命令绑定窗口,从button提起命令。瞧!我希望这可以帮到你
public partial class Window1 : Window
{
public static readonly RoutedCommand Foo = new RoutedCommand();
public Window1()
{
InitializeComponent();
}
void Foo_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
// The Window gets to determine if the Foo
// command can execute at this time.
e.CanExecute = true;
}
void Foo_Executed(object sender, ExecutedRoutedEventArgs e)
{
// The Window executes the command logic when the user wants to Foo.
MessageBox.Show("The Window is Fooing...");
}
}
<Window.CommandBindings>
<CommandBinding
Command="{x:Static local:Window1.Foo}"
CanExecute="Foo_CanExecute"
Executed="Foo_Executed"
/>
我希望我能很好地理解你的问题。
PS:命令设计模式的需要是解耦命令的执行逻辑和调用者.So Command类是一种封装逻辑的方法。答案 3 :(得分:1)
如果不在VS中运行代码,判断你做了什么,问题是你调用InitializeComponent
(渲染XAML),然后设置DataContext
,test
没有任何值属性,最后设置一个私有成员。 UI如何注意到你的命令不再为null(这是它在属性中找到的最后一个值)?
为什么不像这样懒惰地发布命令:
public ICommand test
{
get
{
if(testCommand== null)
{
testCommand= new MeCommand(processor);
}
return testCommand;
}
}
这样它会在需要时立即存在,并且您不需要更改通知(除非您稍后在运行时更改该命令)。
顺便说一下,在命令绑定场景中,您可以感觉到没有执行任何代码的位置:
1)CanExecute()返回false:只返回true或根据您的业务案例进行评估。
2)CanExecute的条件发生变化,因此它将返回true,但不会被调用:您可以使用CommandManager类挂起Command,请参阅here。在尝试之前,请确保1)已解决。这可以确保您的用户界面会频繁地重新查询CanExecute
,如果仍然不够,请明确调用方法CommandManager.InvalidateRequerySuggested()
。
3)你的绑定是错误的。像这样更改绑定代码:
Command="{Binding Path=test, PresentationTraceSources.TraceLevel=High}"
每当拉动或推送绑定的值时,这将垃圾邮件输出窗口。注意“使用最终值”这个术语。如果它为null,则命令不是它应该的位置。
答案 4 :(得分:0)
public ICommand test
{
get { return testCommand; }
set { testCOmmand = value; NotifyPropertyChanged("test"); }
}
到这里。
你也可以这样做 test = new MeCOmmand(); DataContext = this;
答案 5 :(得分:0)
在WPF窗口构造函数中,要链接键盘快捷键,只需使用委托添加绑定,并将其与键手势相关联。
public YourWindow() //your constructor
{
...
//bind keyboard command shortcuts
InputBindings.Add(new KeyBinding( //add a new key-binding, bind it to your command object which takes a delegate
new WindowCommand(this)
{
ExecuteDelegate = TogglePause //REPLACE TogglePause with your method delegate
}, new KeyGesture(Key.P, ModifierKeys.Control)));
...
}
创建一个简单的WindowCommand类,它接受一个执行委托来触发任何设置的方法。
public class WindowCommand : ICommand
{
private MainWindow _window;
public Action ExecuteDelegate { get; set; }
public WindowCommand(MainWindow window)
{
_window = window;
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
if (ExecuteDelegate != null)
{
ExecuteDelegate();
}
else
{
throw new InvalidOperationException();
}
}
}