Silverlight 调用命令时";输入“;键在XAML中按下
当在Silverlight 调用命令时";输入“;键在XAML中按下,silverlight,xaml,eventtrigger,invoke-command,Silverlight,Xaml,Eventtrigger,Invoke Command,当在文本框中按ENTER键时,我想调用一个命令。考虑下面的XAML: <UserControl ... xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" ...> ... <TextBox> <i:Interaction.Triggers>
文本框中按ENTER键时,我想调用一个命令。考虑下面的XAML:
<UserControl
...
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
...>
...
<TextBox>
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyUp">
<i:InvokeCommandAction Command="{Binding MyCommand}"
CommandParameter="{Binding Text}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
...
</UserControl>
...
...
我的命令如下:
public ICommand MyCommand {
get { return new DelegateCommand<string>(MyCommandExecute); }
}
private void MyCommandExecute(string s) { ... }
public ICommand MyCommand{
获取{returnnewdelegatecommand(MyCommandExecute);}
}
私有void MyCommandExecute(字符串s){…}
通过以上步骤,每次按键都会调用我的命令。如何将命令限制为仅在按下ENTER键时调用
< P>我知道,使用表达式混合,我可以使用条件,但那些似乎只限于元素,不能考虑事件参数。
我还遇到过这样一个例子,它提供了自己的InvokeCommandAction
实现,它构建在Systems.Windows.Interactivity
实现之上,可以做我需要的事情。另一个考虑是编写自己的触发器,但我希望有一种不用外部工具包就能完成的方法 在我脑海中。。您可以将事件参数传递给命令,然后在ViewModel中检查e.KeyPress=Keys。输入。。这不是真正的代码:)我没有我的VS在这台计算机上。。这是一个想法:)我昨天遇到了同样的问题,并使用自定义触发器解决了它。一开始可能看起来有点多,但我发现这个通用模式可以用来做很多事情,我曾经在视图中直接使用事件处理程序来完成这些事情(比如双击事件)。第一步是创建一个可以接受参数的触发器操作,因为我们以后需要它
public class ExecuteCommandAction : TriggerAction<FrameworkElement>
{
public string Command { get; set; }
protected override void Invoke(object o)
{
if (Command != null)
{
object ctx = AssociatedObject.DataContext;
if (ctx != null)
{
var cmd = ctx.GetType().GetProperty(Command)
.GetValue(ctx, null) as ICommand;
if (cmd != null && cmd.CanExecute(o))
{
cmd.Execute(o);
}
}
}
}
}
公共类ExecuteCommandAction:TriggerAction
{
公共字符串命令{get;set;}
受保护的覆盖无效调用(对象o)
{
if(命令!=null)
{
对象ctx=AssociatedObject.DataContext;
如果(ctx!=null)
{
var cmd=ctx.GetType().GetProperty(命令)
.GetValue(ctx,null)作为ICommand;
如果(cmd!=null&&cmd.CanExecute(o))
{
命令执行(o);
}
}
}
}
}
下一步是创建触发器。您可以使用基类做一些有趣的事情,使其更通用,以捕获不同类型的按键,但我们将保持简单
public class TextBoxEnterKeyTrigger: TriggerBase<UIElement>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.KeyUp += AssociatedObject_KeyUp;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.KeyUp -= AssociatedObject_KeyUp;
}
void AssociatedObject_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
TextBox textBox = AssociatedObject as TextBox;
object o = textBox == null ? null : textBox.Text;
if (o != null)
{
InvokeActions(o);
}
}
}
}
公共类TextBoxEnterKeyTrigger:TriggerBase
{
受保护的覆盖无效附加()
{
base.onatached();
AssociatedObject.KeyUp+=AssociatedObject\u KeyUp;
}
附加时受保护的覆盖无效()
{
base.OnDetaching();
AssociatedObject.KeyUp-=AssociatedObject\u KeyUp;
}
无效关联对象\u KeyUp(对象发送方,System.Windows.Input.KeyEventArgs e)
{
如果(e.Key==Key.Enter)
{
TextBox TextBox=关联对象为TextBox;
对象o=textBox==null?null:textBox.Text;
如果(o!=null)
{
调用(o);
}
}
}
}
请记住,即使您的TextBox值有数据绑定,属性更改事件也不会触发,因为您的TextBox没有失去焦点。因此,我将TextBox.Text属性的值传递给命令。最后一步是在XAML中使用此功能。您需要确保包括交互性名称空间以及包含上面代码的名称空间
<UserControl
...
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:common="clr-namespace:My.UI;assembly=My.UI">
<TextBox Text="{Binding Path=MyText, Mode=TwoWay}" IsEnabled="{Binding CanMyCommand}">
<i:Interaction.Triggers>
<common:TextBoxEnterKeyTrigger>
<common:ExecuteCommandAction Command=MyCommand" />
</common:TextBoxEnterKeyTrigger>
</i:Interaction.Triggers>
</TextBox>
</UserControl>
我喜欢scottrudy的方法(我给了它+1)和自定义触发器方法,因为它与我最初的方法保持一致。我在下面添加了它的一个修改版本,使用依赖属性而不是反射信息,这样就可以直接绑定到ICommand。我还包括一种使用附加属性的方法,以避免在需要时使用System.Windows.Interactivity
。后一种方法需要注意的是,您失去了一个事件的多个调用功能,但您可以更普遍地应用它
自定义触发器方法
ExecuteCommandAction.cs
public class ExecuteCommandAction : TriggerAction<DependencyObject> {
#region Properties
public ICommand Command {
get { return (ICommand)base.GetValue(CommandProperty); }
set { base.SetValue(CommandProperty, value); }
}
public static ICommand GetCommand(DependencyObject obj) {
return (ICommand)obj.GetValue(CommandProperty);
}
public static void SetCommand(DependencyObject obj, ICommand value) {
obj.SetValue(CommandProperty, value);
}
// We use a DependencyProperty so we can bind commands directly rather
// than have to use reflection info to find them
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(ExecuteCommandAction), null);
#endregion Properties
protected override void Invoke(object parameter) {
ICommand command = Command ?? GetCommand(AssociatedObject);
if (command != null && command.CanExecute(parameter)) {
command.Execute(parameter);
}
}
}
MyUserControl.xaml
<UserControl
...
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:b="clr-namespace:MyNameSpace.Interactivity"
...
<TextBox>
<i:Interaction.Triggers>
<b:TextBoxEnterKeyTrigger>
<b:ExecuteCommandAction Command="{Binding MyCommand}" />
</b:TextBoxEnterKeyTrigger>
</i:Interaction.Triggers>
</TextBox>
...
</UserControl>
<UserControl
...
xmlns:b="clr-namespace:MyNameSpace.Interactivity"
...
<TextBox b:EnterKeyDown.Command="{Binding AddNewDetailCommand}"
b:EnterKeyDown.CommandArgument="{Binding Path=Text,RelativeSource={RelativeSource Self}}" />
...
</UserControl>
我在应用程序中使用了scottrudy的代码,但是,我的文本框文本绑定到viewmodel类中的某个属性,并且在按ENTER键后调用命令时,该属性不会得到更新,因为我的文本框尚未失去焦点。所以,为了解决这个问题,我在AssociatedObject_KeyUp方法的InvokeActions(o)上方添加了以下代码片段,更新的文本属性在viewmodel类中得到更新
BindingExpression bindingExpression = (textBox).GetBindingExpression(TextBox.TextProperty);
bindingExpression.UpdateSource();
在表达上存在着交融
<UserControl
xmlns:i="clr-namespace:System.Windows.Interactivity;
assembly=System.Windows.Interactivity"
xmlns:iex="clr-namespace:Microsoft.Expression.Interactivity.Input;
assembly=Microsoft.Expression.Interactions" ...>
<TextBox>
<i:Interaction.Triggers>
<iex:KeyTrigger Key="Enter">
<i:InvokeCommandAction Command="{Binding PasswordLoginCommand}" />
</iex:KeyTrigger>
</i:Interaction.Triggers>
</TextBox>
</UserControl>
System.Windows.Interactivity
和Microsoft.Expression.Interactivity
程序集可用于官方的WPF。这并不比挂接文本框的KeyUp或KeyPress事件,并在事件处理程序中调用命令(如果e.Key==ENTER)要好。所以,这需要命令避免的紧密耦合……我要求用XAML解决这个问题;检查ViewModel中的键只需添加另一个层来处理具有代码隐藏的事件,这可以在视图(而不是视图模型)中轻松完成。此外,这样的事件处理无论如何都不应该发生在视图模型中=)+1的自定义触发器方法中-我在回答中与另一种方法一起对其进行了修改。有趣。。我在ExecuteCommandAction上遇到了问题,并加入了I:InvokeCommandAction,因为我无论如何都有引用,它工作得很好。我只是想说,这是解决我问题的一个很好的方法。非常感谢:)我现在有一个问题,当我按enter键时,值还没有设置,命令得到ex
BindingExpression bindingExpression = (textBox).GetBindingExpression(TextBox.TextProperty);
bindingExpression.UpdateSource();
<UserControl
xmlns:i="clr-namespace:System.Windows.Interactivity;
assembly=System.Windows.Interactivity"
xmlns:iex="clr-namespace:Microsoft.Expression.Interactivity.Input;
assembly=Microsoft.Expression.Interactions" ...>
<TextBox>
<i:Interaction.Triggers>
<iex:KeyTrigger Key="Enter">
<i:InvokeCommandAction Command="{Binding PasswordLoginCommand}" />
</iex:KeyTrigger>
</i:Interaction.Triggers>
</TextBox>
</UserControl>