WPF将命令附加到NET3.5中返回键上的文本框

WPF将命令附加到NET3.5中返回键上的文本框,wpf,textbox,.net-3.5,key-bindings,inputbinding,Wpf,Textbox,.net 3.5,Key Bindings,Inputbinding,我试图在返回键上将命令和commandparameter附加到文本框,但没有成功。该参数是同一文本框中的当前文本 <TextBox x:Name="txtSearch"> <TextBox.InputBindings> <KeyBinding Command="{Binding SearchCommand}" CommandParameter="{Binding Path=Text, Elem

我试图在返回键上将命令和commandparameter附加到文本框,但没有成功。该参数是同一文本框中的当前文本

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

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

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

我发现在.NET3.5中,keybinding的命令参数不接受绑定。因此,代码隐藏中的代码提出了一个解决方案,但如何从代码中将参数传递给命令?

首先,您需要将键绑定添加到文本框中,并将其命令设置为代码隐藏。只需在视图的构造函数中添加以下内容:

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
    }
}
public class ObservableObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
如果您有权访问C#6(Visual Studio 2015及更高版本),则可以将对OnPropertyChanged的调用更改为:
OnPropertyChanged(nameof(TxtSearch))。通过这种方式,您摆脱了“魔术字符串”,并且最终重命名属性不会给您带来任何问题

然后您的XAML应该是这样的:(注意,您需要指定te UpdateSourceTrigger必须是PropertyChanged,这样当您点击文本框上的
Enter
键时,ViewModel的
TxtSearch
属性保持最新

<TextBox Text="{Binding TxtSearch, UpdateSourceTrigger=PropertyChanged}" x:Name="txtSearch"/>    
这是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; }
    }
}
公共类RelayCommand:ICommand
{
私有谓词_canExecute;
私人行动——执行;
公共RelayCommand(谓词canExecute、操作execute)
{
_canExecute=canExecute;
_执行=执行;
}
公共布尔CanExecute(对象参数)
{
返回_canExecute(参数);
}
public void Execute(对象参数)
{
_执行(参数);
}
公共事件事件处理程序CanExecuteChanged
{
添加{CommandManager.RequerySuggested+=value;}
删除{CommandManager.RequerySuggested-=value;}
}
}

编译器显示以下错误:无法在“keybinding”类型的“command”属性上设置“binding”。只能在DependencyObject的DependencyProperty上设置“binding”。请记住,我使用的是.NET 3.5。那么,您必须从后面的代码创建命令绑定。我将很快编辑我的答案。