문제

어떻게 관리할 수 있습니다.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>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top