I have a topmost dialog box that hides itself when someone presses a button or hits escape.
(Code shown is a much simplified version to highlight the issue encountered.)
If I launch the dialog as follows everything works fine.
var dialog = new MyDialog(new MyDialogViewModel());
n开发者_如何学JAVAew Application().Run(dialog);
If I open the dialog as follows then the escape key binding won't work but the button still does.
new MyDialog(new MyDialogViewModel()).Show();
MyDialog.xaml
<Window x:Class="MyDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Topmost="True"
Visibility="{Binding Visibility}">
<Window.InputBindings>
<KeyBinding Key="Escape" Command="{Binding HideCommand}" />
</Window.InputBindings>
<Button Command="{Binding HideCommand}">Hide</Button>
</Window>
MyDialog.xaml.cs
public partial class MyDialog : Window
{
public MyDialog(MyDialogViewModel vm)
{
DataContext = vm;
InitializeComponent();
}
}
MyDialogViewModel.cs
public class MyDialogViewModel : INotifyPropertyChanged
{
private Visibility _visibility = Visibility.Visible;
public MyDialogViewModel()
{
HideCommand = new DelegateCommand(Hide);
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public DelegateCommand HideCommand { get; private set; }
public Visibility Visibility
{
get
{
return _visibility;
}
set
{
_visibility = value;
PropertyChanged();
}
}
private void Hide()
{
Visibility = Visibility.Hidden;
}
}
Using Snoop I can see the following binding error, this is present when launched either way.
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=HideCommand; DataItem=null; target element is 'KeyBinding' (HashCode=30871361); target property is 'Command' (type 'ICommand')
I'm trying to understand why the escape key works in one scenario and not the other. Any ideas?
A few thoughts/questions:
In the version that does not work, where are you opening the dialog? From the main window that is started by the application?
In your MyDialog constructor, I'm assuming you have a call to InitializeComponent. Is that correct? Otherwise, it would not properly initialize from the XAML file.
Is there a reason you cannot use the Button.IsCancel property?
EDIT:
If you are loading a WPF Window from a WinForms application you need to do some additional work. This blog explains this and includes the following example:
using System;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
....
var wpfwindow = new WPFWindow.Window1();
ElementHost.EnableModelessKeyboardInterop(wpfwindow);
wpfwindow.Show();
I wonder if it's a timing issue with the KeyBinding. I just checked one of my projects that has tons of KeyBinding and the commands are all static so there would be no issue. I wonder if perhaps the KeyBinding command binding is occurring before the VM is updated and the binding is never being updated.
UPDATE: Check this out, it may be the answer: http://joyfulwpf.blogspot.com/2009/05/mvvm-commandreference-and-keybinding.html
and this: Keybinding a RelayCommand
精彩评论