문제
어떻게 관리할 수 있습니다.KeyDown 이벤트 코드를 사용하지 않고 숨김?우리가 사용하려고된 이 패턴과를 쓰는 코드에서 이벤트 처리기 뒤에 파일입니다.
해결책
조금 늦었지만,여기에 간다.
Microsoft WPF 팀은 최근에 발표했는 초기 버전의 자신 WPF 된 이 Toolkit .에 그것은,당신은 클래스를 찾을 불 CommandReference 처리할 수 있는 것과 같은 키를 지원합니다.의 WPF 된 이 템플릿을 어떻게 작동하는지 볼 수 있습니다.
다른 팁
을 가지고 업데이트 된답니다.net framework4.0 이 작업을 수행할 수 있습니다 잘 시켜서 당신은 바인딩 해제 명령 명령에서 뷰 모델.
그래서...면을 듣고 Enter 키를,당신은 다음과 같은 것이 가능합니다.
<TextBox AcceptsReturn="False">
<TextBox.InputBindings>
<KeyBinding
Key="Enter"
Command="{Binding SearchCommand}"
CommandParameter="{Binding Path=Text, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}" />
</TextBox.InputBindings>
</TextBox>
와우-가의 천 답변과 여기에 나는 다른 추가니다.
정말 분명한 것은'왜-지 않았-I-실-이-이마-슬랩'종류의 방법으로는 코드는 뒤에고 ViewModel
앉아 같은 방에 이렇게 말하는,그래서 거기에 아무 이유 없이 왜 그들이 허용하지 않는 대화를해야합니다.
당신이 그것에 대하여 생각하는 경우,XAML 은 이미 이 친밀하게 결합된 뷰 모델의 API,그래서 당신은 단지뿐만 아니라 이동 및 확인에 종속에서 코드의 뒤에 있습니다.
다른 분명한 규칙이 순종하나를 무시하도 적용(인터페이스,null 검사 <특히 사용할 경우 혼...)
난 항상 만들기 시설 코드에서 뒤에 다음과 같다:
private ViewModelClass ViewModel { get { return DataContext as ViewModelClass; } }
이것은 클라이언트-코드입니다.Null 체크에 대한 도움을 제어 호스팅으로 다음과 같문 조사를 진행하고 있습니다.
void someEventHandler(object sender, KeyDownEventArgs e)
{
if (ViewModel == null) return;
/* ... */
ViewModel.HandleKeyDown(e);
}
핸들의 이벤트 코드에서 뒤에 당신 같은 원하는 UI(이벤트는 UI 를 중심의 확인)다음 방법에 ViewModelClass 는에 반응할 수 있는 이벤트입니다.문제는 여전히 분리했습니다 있습니다.
ViewModelClass
{
public void HandleKeyDown(KeyEventArgs e) { /* ... */ }
}
이러한 모든 다른 부착된 특성 및 부두는 것은 매우 시원하고 기술은 정말 유용한 몇 가지 다른 것들,그러나 여기에 멀리 얻을 수 있으로 무언가가 간단하...
나는 이것을 이용하여 첨부된 행동은 3 개의 종속성 속성은;하나는 명령을 실행,하나은 매개변수를 통하여 명령어와 다른 키를 일으키는 원인이 될 것이다 명령어를 실행할 수 있습니다.여기에는 코드:
public static class CreateKeyDownCommandBinding
{
/// <summary>
/// Command to execute.
/// </summary>
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command",
typeof(CommandModelBase),
typeof(CreateKeyDownCommandBinding),
new PropertyMetadata(new PropertyChangedCallback(OnCommandInvalidated)));
/// <summary>
/// Parameter to be passed to the command.
/// </summary>
public static readonly DependencyProperty ParameterProperty =
DependencyProperty.RegisterAttached("Parameter",
typeof(object),
typeof(CreateKeyDownCommandBinding),
new PropertyMetadata(new PropertyChangedCallback(OnParameterInvalidated)));
/// <summary>
/// The key to be used as a trigger to execute the command.
/// </summary>
public static readonly DependencyProperty KeyProperty =
DependencyProperty.RegisterAttached("Key",
typeof(Key),
typeof(CreateKeyDownCommandBinding));
/// <summary>
/// Get the command to execute.
/// </summary>
/// <param name="sender"></param>
/// <returns></returns>
public static CommandModelBase GetCommand(DependencyObject sender)
{
return (CommandModelBase)sender.GetValue(CommandProperty);
}
/// <summary>
/// Set the command to execute.
/// </summary>
/// <param name="sender"></param>
/// <param name="command"></param>
public static void SetCommand(DependencyObject sender, CommandModelBase command)
{
sender.SetValue(CommandProperty, command);
}
/// <summary>
/// Get the parameter to pass to the command.
/// </summary>
/// <param name="sender"></param>
/// <returns></returns>
public static object GetParameter(DependencyObject sender)
{
return sender.GetValue(ParameterProperty);
}
/// <summary>
/// Set the parameter to pass to the command.
/// </summary>
/// <param name="sender"></param>
/// <param name="parameter"></param>
public static void SetParameter(DependencyObject sender, object parameter)
{
sender.SetValue(ParameterProperty, parameter);
}
/// <summary>
/// Get the key to trigger the command.
/// </summary>
/// <param name="sender"></param>
/// <returns></returns>
public static Key GetKey(DependencyObject sender)
{
return (Key)sender.GetValue(KeyProperty);
}
/// <summary>
/// Set the key which triggers the command.
/// </summary>
/// <param name="sender"></param>
/// <param name="key"></param>
public static void SetKey(DependencyObject sender, Key key)
{
sender.SetValue(KeyProperty, key);
}
/// <summary>
/// When the command property is being set attach a listener for the
/// key down event. When the command is being unset (when the
/// UIElement is unloaded for instance) remove the listener.
/// </summary>
/// <param name="dependencyObject"></param>
/// <param name="e"></param>
static void OnCommandInvalidated(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
UIElement element = (UIElement)dependencyObject;
if (e.OldValue == null && e.NewValue != null)
{
element.AddHandler(UIElement.KeyDownEvent,
new KeyEventHandler(OnKeyDown), true);
}
if (e.OldValue != null && e.NewValue == null)
{
element.RemoveHandler(UIElement.KeyDownEvent,
new KeyEventHandler(OnKeyDown));
}
}
/// <summary>
/// When the parameter property is set update the command binding to
/// include it.
/// </summary>
/// <param name="dependencyObject"></param>
/// <param name="e"></param>
static void OnParameterInvalidated(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
UIElement element = (UIElement)dependencyObject;
element.CommandBindings.Clear();
// Setup the binding
CommandModelBase commandModel = e.NewValue as CommandModelBase;
if (commandModel != null)
{
element.CommandBindings.Add(new CommandBinding(commandModel.Command,
commandModel.OnExecute, commandModel.OnQueryEnabled));
}
}
/// <summary>
/// When the trigger key is pressed on the element, check whether
/// the command should execute and then execute it.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnKeyDown(object sender, KeyEventArgs e)
{
UIElement element = sender as UIElement;
Key triggerKey = (Key)element.GetValue(KeyProperty);
if (e.Key != triggerKey)
{
return;
}
CommandModelBase cmdModel = (CommandModelBase)element.GetValue(CommandProperty);
object parameter = element.GetValue(ParameterProperty);
if (cmdModel.CanExecute(parameter))
{
cmdModel.Execute(parameter);
}
e.Handled = true;
}
}
을 사용하여 이 xaml 에서 당신은 다음과 같이 할 수 있다:
<TextBox framework:CreateKeyDownCommandBinding.Command="{Binding MyCommand}">
<framework:CreateKeyDownCommandBinding.Key>Enter</framework:CreateKeyDownCommandBinding.Key>
</TextBox>
편집: CommandModelBase 기본 클래스에 사용하는 모든 명령입니다.그것을 기반으로 CommandModel 클래스에서 댄 Crevier 의 문서에된 이(기).여기에는 소스에 대한 약간 수정 버전 사용으로 CreateKeyDownCommandBinding:
public abstract class CommandModelBase : ICommand
{
RoutedCommand routedCommand_;
/// <summary>
/// Expose a command that can be bound to from XAML.
/// </summary>
public RoutedCommand Command
{
get { return routedCommand_; }
}
/// <summary>
/// Initialise the command.
/// </summary>
public CommandModelBase()
{
routedCommand_ = new RoutedCommand();
}
/// <summary>
/// Default implementation always allows the command to execute.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void OnQueryEnabled(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = CanExecute(e.Parameter);
e.Handled = true;
}
/// <summary>
/// Subclasses must provide the execution logic.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void OnExecute(object sender, ExecutedRoutedEventArgs e)
{
Execute(e.Parameter);
}
#region ICommand Members
public virtual bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public abstract void Execute(object parameter);
#endregion
}
의 의견과 제안을 개선에 대한 것을 환영합니다.
동물이 어미가 총을 맞았기 때문에 왔는 문제는 몇 달 전,그리고 내가 쓴 마 확장자는 않습니다.그것처럼 사용할 수 있습니다 일반 binding:
<Window.InputBindings>
<KeyBinding Key="E" Modifiers="Control" Command="{input:CommandBinding EditCommand}"/>
</Window.InputBindings>
전체 소스 코드를 이 확장은 여기에서 찾을 수 있습니다:
http://www.thomaslevesque.com/2009/03/17/wpf-using-inputbindings-with-the-mvvm-pattern/
이는 해결 방법은 아마 매우""깨끗한,사용하기 때문에 일부 개인 클래스와 필드를 반영...
짧은 대답입니다 당신은 처리할 수 없는 직선 키보드를 입력하지 않고 이벤트 코드는 뒤에,하지만 당신은 처리할 수 있는 InputBindings 과된 이(보여줄 수 있습니다 당신은 관련된 예는 경우 이것은 당신이 필요로하는 것입니다).
할 수 있습니에 대한 자세한 정보를 제공하는 당신이 원하는 무슨을에서 핸들러는?
코드 뒤에되지 않을 피할 것으로 완전히된 이.그것은 단순히 사용에 대한 엄격하게 UI 관련 작업과 관련이 있습니다.기경 예로 들 수 있는 몇 가지 유형의 데이터 입력 형태'를 읽어들이는 경우,필요에 포커스를 설정할 수 있는 첫 번째 입소자(text box,콤,무엇이든).당신은 일반적으로 할당하는 요소는 x:이름 속성을 걸 창/페이지/정렬의'로드'이벤트를 초점을 설정하는 요소입니다.이것은 완벽하게 확인하여 패턴이기 때문에 이 작업은 UI 를 중심하고는 아무것도 할 데이터와 함께 나타냅니다.
이 질문은 아주 오래된,하지만 난 그 이기 때문에 이러한 유형의 기능이었다 그냥 쉽게 만들어를 구현하는 Silverlight(5).그래서 어쩌면 다른 사람이 올해도 여기에있다.
이 간단한 솔루션을 후 나는 찾을 수 없습니다 내가 무엇을 찾고 있었습니다.설 오히려 간단합니다.그것은 작동해야에서 모두 Silverlight5WPF.
public class KeyToCommandExtension : IMarkupExtension<Delegate>
{
public string Command { get; set; }
public Key Key { get; set; }
private void KeyEvent(object sender, KeyEventArgs e)
{
if (Key != Key.None && e.Key != Key) return;
var target = (FrameworkElement)sender;
if (target.DataContext == null) return;
var property = target.DataContext.GetType().GetProperty(Command, BindingFlags.Public | BindingFlags.Instance, null, typeof(ICommand), new Type[0], null);
if (property == null) return;
var command = (ICommand)property.GetValue(target.DataContext, null);
if (command != null && command.CanExecute(Key))
command.Execute(Key);
}
public Delegate ProvideValue(IServiceProvider serviceProvider)
{
if (string.IsNullOrEmpty(Command))
throw new InvalidOperationException("Command not set");
var targetProvider = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
if (!(targetProvider.TargetObject is FrameworkElement))
throw new InvalidOperationException("Target object must be FrameworkElement");
if (!(targetProvider.TargetProperty is EventInfo))
throw new InvalidOperationException("Target property must be event");
return Delegate.CreateDelegate(typeof(KeyEventHandler), this, "KeyEvent");
}
사용법:
<TextBox KeyUp="{MarkupExtensions:KeyToCommand Command=LoginCommand, Key=Enter}"/>
알 Command
은 문자열이 아닌 바인딩 가능 ICommand
.내가 이것을 알고 있는 유연하지만,그것은 청소기 때 사용하고,필요 시간의 99%.하지만 그것이 문제가되지 않습니다.
비슷한 karlipoppins 대답하지만,내가 그것을 발견이 작동하지 않지 않고 다음과 같은 추가/변경:
<TextBox Text="{Binding UploadNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding FindUploadCommand}" />
</TextBox.InputBindings>
</TextBox>