wpf Caliburn Micro“进入”关键事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16719496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Caliburn Micro 'Enter' Key Event
提问by spugm1r3
I am attempting to bind an event with Caliburn Micro and I am having some issues getting the right messages to the method. I would like to add the ability to press the 'Enter' key after changing the value in a text box and it execute the same method that the button next to is bound to. However, regardless of which key is pressed, I get the following exceptions:
我正在尝试将事件与 Caliburn Micro 绑定,但在向该方法获取正确消息时遇到了一些问题。我想添加在更改文本框中的值后按“Enter”键的功能,它执行与旁边按钮绑定的相同方法。但是,无论按下哪个键,都会出现以下异常:
A first chance exception of type 'System.InvalidCastException' occurred in MyApp.exe
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
A first chance exception of type 'System.Reflection.TargetInvocationException' occurred in WindowsBase.dll
MyApp.exe 中发生了“System.InvalidCastException”类型的第一次机会异常
mscorlib.dll 中发生了“System.Reflection.TargetInvocationException”类型的第一次机会异常
WindowsBase.dll 中发生了“System.Reflection.TargetInvocationException”类型的第一次机会异常
At the suggestion of another, similar question Binding KeyDown Event Silverlight, I've tried using ActionExecutionContext, but to no avail.
在另一个类似问题Binding KeyDown Event Silverlight的建议下,我尝试使用 ActionExecutionContext,但无济于事。
Here is the xaml:
这是xaml:
<TextBox Name="Threshold"
Margin="5"
Grid.Column="1"
>
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyDown">
<cal:ActionMessage MethodName="ExecuteFilterView">
<cal:Parameter Value="$executionContext"/>
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
And the method:
和方法:
public void ExecuteFilterView(ActionExecutionContext context)
{
//Do stuff...
}
I understand that I could probably save myself some headaches and simply do a standard event handler in the code behind, but this app is an exercise in MVVM and learning to utilize Caliburn.Micro, so I would like to stick with making this particular approach work.
我知道我可能会为自己省去一些麻烦,只需在后面的代码中做一个标准的事件处理程序,但这个应用程序是 MVVM 中的一个练习,并学习使用 Caliburn.Micro,所以我想坚持让这种特殊的方法起作用.
Am I just trying to send the wrong information from the event? Is my xaml not coded properly to get what I want? Or I have missed something else entirely?
我只是想从事件中发送错误的信息吗?我的 xaml 是否没有正确编码以获得我想要的?或者我完全错过了其他东西?
回答by Charleh
Just threw a test together, both of these work for me:
刚刚进行了一个测试,这两个都对我有用:
Using full syntax:
使用完整语法:
<TextBox Name="Threshold"
Margin="5"
Grid.Column="1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyDown">
<cal:ActionMessage MethodName="ExecuteFilterView">
<cal:Parameter Value="$executionContext"/>
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
Using CM syntax (prefer this as it's way more readable)
使用 CM 语法(更喜欢这个,因为它更具可读性)
<TextBox Name="Threshold"
Margin="5"
Grid.Column="1"
cal:Message.Attach="[Event KeyDown] = [Action ExecuteFilterView($executionContext)]" />
This was the test VM:
这是测试虚拟机:
public class MainWindowViewModel
{
public void ExecuteFilterView(ActionExecutionContext context)
{
// This method is hit and the context is present and correct
}
}
Can you post your full code - are you sure you have the framework setup correctly? (have you followed the getting started example?
你能发布你的完整代码 - 你确定你的框架设置正确吗?(您是否遵循了入门示例?
Edit:
编辑:
Ok after your clarification I can give you some examples of how to do this - I'll tell you my personal preference and why, but choose the one that fits you best
好的,在您澄清之后,我可以给您一些如何执行此操作的示例 - 我会告诉您我的个人偏好以及原因,但请选择最适合您的
- Using
ActionExecutionContextand casting the eventargs:
- 使用
ActionExecutionContext和转换 eventargs:
cal:Message.Attach="[Event KeyDown] = [Action ExecuteFilterView($executionContext)]"
public void ExecuteFilterView(ActionExecutionContext context)
{
var keyArgs = context.EventArgs as KeyEventArgs;
if (keyArgs != null && keyArgs.Key == Key.Enter)
{
// Do Stuff
}
}
- Using
EventArgsdirectly
EventArgs直接使用
cal:Message.Attach="[Event KeyDown] = [Action ExecuteFilterView($eventArgs)]"
public void ExecuteFilterView(KeyEventArgs keyArgs)
{
if (keyArgs.Key == Key.Enter)
{
// Do Stuff
}
}
- My personal fave, creating your own
SpecialValuesdictionary entry:
- 我个人的最爱,创建自己的
SpecialValues字典条目:
In your Bootstrapper.Configuremethod...
在你的Bootstrapper.Configure方法...
MessageBinder.SpecialValues.Add("$pressedkey", (context) =>
{
// NOTE: IMPORTANT - you MUST add the dictionary key as lowercase as CM
// does a ToLower on the param string you add in the action message, in fact ideally
// all your param messages should be lowercase just in case. I don't really like this
// behaviour but that's how it is!
var keyArgs = context.EventArgs as KeyEventArgs;
if (keyArgs != null)
return keyArgs.Key;
return null;
});
Your action:
你的行动:
cal:Message.Attach="[Event KeyDown] = [Action ExecuteFilterView($pressedKey)]"
And the code:
和代码:
public void ExecuteFilterView(Key key)
{
if (key == Key.Enter)
{
// Do Stuff
}
}
The reason this is my favourite? It means that your VM just receives the value you want (most of the time you don't care about a lot of the other parameters) and you don't need to know how to or bother to cast the eventargs - you can just operate on the value. Obviously use whatever is best for you
这是我最喜欢的原因?这意味着您的 VM 只会收到您想要的值(大多数时候您并不关心很多其他参数)并且您不需要知道如何或费心去转换 eventargs - 您可以直接操作在价值上。显然使用最适合你的
It's also worth noting, that if you have other types of controls that subclass KeyEventArgsthis will work for them. If they don't subclass KeyEventArgsbut they still return a value of type Keythis will still work too as you can just add another cast to the delegate if the first one fails:
还值得注意的是,如果您有其他类型的控件子类,KeyEventArgs这将适用于它们。如果他们没有子类化KeyEventArgs但他们仍然返回一个类型的值,Key这仍然可以工作,因为如果第一个失败,您可以向委托添加另一个强制转换:
e.g.
例如
MessageBinder.SpecialValues.Add("$pressedkey", (context) =>
{
var keyArgs = context.EventArgs as KeyEventArgs;
if (keyArgs != null)
return keyArgs.Key;
// Ok so it wasn't KeyEventArgs... check for some other type - maybe a 3rd party implementation
var thirdPartyKeyArgs = context.EventArgs as ThirdPartyKeyArgs;
if (thirdPartyKeyArgs != null)
return thirdPartyKeyArgs.KeyProperty;
return null;
});
回答by kuberzzz333
If using keyeventargs as parameter type , and it gives u back null ,then look at this:
You propably using System.Windows.Forms.KeyEventArgsand KeyEventArgs, as parameter type is refering to this, try with System.Windows.Input.KeyEventArgs(it works for me).
如果使用 keyeventargs 作为参数类型,并且它给你返回 null ,那么看看这个:你可能使用System.Windows.Forms.KeyEventArgsand KeyEventArgs,因为参数类型是指这个,试试System.Windows.Input.KeyEventArgs(它对我有用)。
public void ExecuteFilterView(System.Windows.Input.KeyEventArgs context)
{
if(context.Key==System.Windows.Input.Key.Return)
{
//action here
}
}

