WPF 将命令附加到 NET 3.5 中 return 键上的文本框

WPF Attach a command to a textbox on return key in NET 3.5

我正在尝试将命令和命令参数附加到 return 键上的文本框,但没有成功。参数为同一文本框中的当前文本。

<TextBox x:Name="txtSearch">
    <TextBox.InputBindings>
         <KeyBinding  Command="{Binding SearchCommand}" 
                      CommandParameter="{Binding Path=Text, ElementName=txtSearch}" Key="Return" />
    </TextBox.InputBindings>
</TextBox>

基本上我想在用户单击 return/enter 键时执行命令并将文本框中的当前文本作为参数传递。

我发现这个 link 据说在 .NET 3.5 中用于键绑定的命令参数不接受绑定。所以代码隐藏中的代码提出了一个解决方案,但是我如何从代码中将参数传递给命令?

首先,您需要将 KeyBinding 添加到您的 TextBox 并将其命令设置为代码隐藏。只需将其添加到视图的构造函数中:

public MainWindow()
{
    InitializeComponent();
    DataContext = new MyViewModel();

    KeyBinding kb = new KeyBinding();
    kb.Command = (DataContext as MyViewModel).SearchCommand;                        
    kb.Key = Key.Enter;
    txtSearch.InputBindings.Add(kb);
}

然后,您可以将名为 txtSearch 的文本框的 Text 属性 绑定到您的 ViewModel 的 属性。这样您就不需要传递参数,因为您可以在执行命令的代码中的 ViewModel 中使用 属性 的值。

您的 ViewModel 应如下所示:

public class MyViewModel : ObservableObject
{
    private string _txtSearch;
    public string TxtSearch
    {
        get { return _txtSearch; }
        set
        {
            if (value != _txtSearch)
            {
                _txtSearch = value;
                OnPropertyChanged("TxtSearch");
            }
        }
    }

    private ICommand _searchCommand;
    public ICommand SearchCommand
    {
        get
        {
            if (_searchCommand == null)
            {
                _searchCommand = new RelayCommand(p => canSearch(), p => search());
            }
            return _searchCommand;
        }
    }
    private bool canSearch()
    {
        //implement canExecute logic.
    }
    private void search()
    {
        string text = TxtSearch; //here you'll have the string that represents the text of the TextBox txtSearch
        //DoSomething
    }
}

如果您可以访问 C# 6(Visual Studio 2015 及更高版本),则可以将对 OnPropertyChanged 的​​调用更改为:OnPropertyChanged(nameof(TxtSearch));。这样你就可以摆脱 "magic string" 并且最终重命名 属性 不会对你造成任何问题。

然后你的 XAML 应该看起来像这样:(注意你需要指定 te UpdateSourceTrigger 必须是 PropertyChanged,这样你的 ViewModel 的 TxtSearch 属性 保持不变到目前为止,当您点击文本框上的 Enter 键时。

<TextBox Text="{Binding TxtSearch, UpdateSourceTrigger=PropertyChanged}" x:Name="txtSearch"/>    

您的 ViewModel 需要实施 INotifyPropertyChanged 并且您需要适当的 ICommand 实施。这里我将使用 RelayCommand。

这些实现如下所示。

由于您的框架是 .NET 3.5,因此实现它:

public class ObservableObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

这是 RelayCommand 的实现:

public class RelayCommand : ICommand
{
    private Predicate<object> _canExecute;
    private Action<object> _execute;

    public RelayCommand(Predicate<object> canExecute, Action<object> execute)
    {
        _canExecute = canExecute;
        _execute = execute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
}