将WPF文本框事件绑定到命令
我试图找到一个简单的示例,说明如何将一些文本框事件(PreviewTestInput和PreviewKeyDown)绑定到命令,但是我找不到任何清晰的示例,而且我找到的所有ExMaple都强制我使用一些MVVM框架(Light toolkit、Prism等),然而,目前我不想使用框架,因为我想更深入地了解业务是如何运作的将WPF文本框事件绑定到命令,wpf,mvvm,routed-commands,Wpf,Mvvm,Routed Commands,我试图找到一个简单的示例,说明如何将一些文本框事件(PreviewTestInput和PreviewKeyDown)绑定到命令,但是我找不到任何清晰的示例,而且我找到的所有ExMaple都强制我使用一些MVVM框架(Light toolkit、Prism等),然而,目前我不想使用框架,因为我想更深入地了解业务是如何运作的 谁能提供一个简单的例子来说明如何实现这一点 使用MVVM框架是绝对必要的吗 提前感谢。您可以继承并实现。我也这样做了,我的实现看起来像这样。您应该能够将其扩展到PreviewP
public class CommandTextBox : TextBox, ICommandSource
{
private bool _canExecute;
private EventHandler _canExecuteChanged;
/// <summary>
/// DependencyProperty for Command property.
/// </summary>
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandTextBox), new PropertyMetadata(OnCommandChanged));
/// <summary>
/// Gets or sets the command to invoke when the enter key is pressed.
/// </summary>
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
/// <summary>
/// DependencyProperty for CommandParameter property.
/// </summary>
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(CommandTextBox));
/// <summary>
/// Gets or sets the parameter to pass to the Command property.
/// </summary>
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
/// <summary>
/// Gets or sets a value that indicates whether the command resets the text property.
/// </summary>
public bool CommandResetsText { get; set; }
/// <summary>
/// DependencyProperty for CommandTarget property.
/// </summary>
public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(CommandTextBox));
/// <summary>
/// Gets or sets the element on which to raise the specified command.
/// </summary>
public IInputElement CommandTarget
{
get { return (IInputElement)GetValue(CommandTargetProperty); }
set { SetValue(CommandTargetProperty, value); }
}
/// <summary>
/// Gets a value that becomes the return value of
/// System.Windows.UIElement.IsEnabled in derived classes.
/// </summary>
protected override bool IsEnabledCore
{
get { return base.IsEnabledCore && _canExecute; }
}
/// <summary>
/// Command dependency property change callback.
/// </summary>
/// <param name="d">Dependency Object</param>
/// <param name="e">Event Args</param>
private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CommandTextBox tb = (CommandTextBox)d;
tb.HookUpCommand((ICommand)e.OldValue, (ICommand)e.NewValue);
}
/// <summary>
/// If Command is defined, pressing the enter key will invoke the command;
/// Otherwise, the textbox will behave normally.
/// </summary>
/// <param name="e">Provides data about the event.</param>
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.Key == Key.Enter && Command != null)
{
RoutedCommand command = Command as RoutedCommand;
if (command != null)
command.Execute(CommandParameter, CommandTarget);
else
Command.Execute(CommandParameter);
if (CommandResetsText)
this.Text = String.Empty;
}
}
/// <summary>
/// Add a command to the Command Property.
/// </summary>
/// <param name="command">Command</param>
private void AddCommand(ICommand command)
{
var handler = new EventHandler(CanExecuteChanged);
_canExecuteChanged = handler;
if (command != null)
command.CanExecuteChanged += _canExecuteChanged;
}
private void CanExecuteChanged(object sender, EventArgs e)
{
if (Command != null)
{
RoutedCommand command = Command as RoutedCommand;
// If a RoutedCommand.
if (command != null)
_canExecute = command.CanExecute(CommandParameter, CommandTarget);
else
_canExecute = Command.CanExecute(CommandParameter);
}
CoerceValue(UIElement.IsEnabledProperty);
}
/// <summary>
/// Add a new command to the Command Property.
/// </summary>
/// <param name="oldCommand">Old Command</param>
/// <param name="newCommand">New Command</param>
private void HookUpCommand(ICommand oldCommand, ICommand newCommand)
{
// If oldCommand is not null, then we need to remove the handlers.
if (oldCommand != null)
RemoveCommand(oldCommand);
AddCommand(newCommand);
}
/// <summary>
/// Remove a command from the Command Property.
/// </summary>
/// <param name="command">Command</param>
private void RemoveCommand(ICommand command)
{
EventHandler handler = CanExecuteChanged;
command.CanExecuteChanged -= handler;
}
}
公共类命令TextBox:TextBox,ICommandSource
{
私人楼宇可执行;
私有事件处理程序\u canExecuteChanged;
///
///命令属性的DependencyProperty。
///
public static readonly dependencProperty CommandProperty=dependencProperty.Register(“Command”、typeof(ICommand)、typeof(CommandTextBox)、new PropertyMetadata(OnCommandChanged));
///
///获取或设置按下enter键时要调用的命令。
///
公共ICommand命令
{
获取{return(ICommand)GetValue(CommandProperty);}
set{SetValue(CommandProperty,value);}
}
///
///CommandParameter属性的DependencyProperty。
///
public static readonly dependencProperty CommandParameterProperty=dependencProperty.Register(“CommandParameter”、typeof(object)、typeof(CommandTextBox));
///
///获取或设置要传递给命令属性的参数。
///
公共对象命令参数
{
获取{return GetValue(CommandParameterProperty);}
set{SetValue(CommandParameterProperty,value);}
}
///
///获取或设置一个值,该值指示命令是否重置文本属性。
///
公共bool命令resetstext{get;set;}
///
///CommandTarget属性的DependencyProperty。
///
公共静态只读DependencyProperty CommandTargetProperty=DependencyProperty.Register(“CommandTarget”、typeof(IIInputElement)、typeof(CommandTextBox));
///
///获取或设置要在其上引发指定命令的元素。
///
公共IIInputElement命令目标
{
获取{return(IInputElement)GetValue(CommandTargetProperty);}
set{SetValue(CommandTargetProperty,value);}
}
///
///获取一个值,该值将成为的返回值
///System.Windows.UIElement.IsEnabled在派生类中。
///
受保护的覆盖布尔IsEnabledCore
{
获取{return base.IsEnabledCore&&u canExecute;}
}
///
///命令依赖项属性更改回调。
///
///依赖对象
///事件参数
命令上的私有静态无效已更改(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
CommandTextBox tb=(CommandTextBox)d;
tb.HookUpCommand((ICommand)e.OldValue,(ICommand)e.NewValue);
}
///
///如果定义了命令,按enter键将调用该命令;
///否则,文本框将正常工作。
///
///提供有关事件的数据。
受保护的覆盖无效OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
如果(e.Key==Key.Enter&&Command!=null)
{
RoutedCommand=作为RoutedCommand的命令;
if(命令!=null)
command.Execute(CommandParameter,CommandTarget);
其他的
Command.Execute(CommandParameter);
if(CommandResetsText)
this.Text=String.Empty;
}
}
///
///将命令添加到命令属性。
///
///命令
专用void AddCommand(ICommand命令)
{
var handler=neweventhandler(CanExecuteChanged);
_canExecuteChanged=处理程序;
if(命令!=null)
command.CanExecuteChanged+=\u CanExecuteChanged;
}
私有void CanExecuteChanged(对象发送方,事件参数e)
{
if(命令!=null)
{
RoutedCommand=作为RoutedCommand的命令;
//如果是RoutedCommand。
if(命令!=null)
_canExecute=command.canExecute(CommandParameter,CommandTarget);
其他的
_canExecute=Command.canExecute(CommandParameter);
}
强制值(UIElement.IsEnabledProperty);
}
///
///将新命令添加到命令属性。
///
///旧命令
///新命令
专用无效连接命令(ICommand oldCommand、ICommand newCommand)
{
//如果oldCommand不为null,那么我们需要删除处理程序。
if(oldCommand!=null)
RemoveCommand(oldCommand);
AddCommand(newCommand);
}
///
///从命令属性中删除命令。
///
///命令
专用void RemoveCommand(ICommand命令)
{
EventHandler handler=CanExecuteChanged;
command.CanExecuteChanged-=处理程序;
}
}
简单的方法是在XAML中将公共事件处理程序附加到事件,并在代码隐藏中调用命令。此类事件处理程序可能如下所示:
private void TextBox_OnTextChanged(object sender, EventArgs e)
{
var viewmodel = this.DataContext as MyViewmodel;
if (viewmodel != null)
{
viewmodel.SomeCommand.Execute();
}
}
另一种方法是实现自己的MarkupExtension,这样您就可以编写如下代码
<TextBox TextChanged="{myMarkupExtension:CommandBinding SomeCommand]">...</TextBox>
。。。
有几篇文章描述了这种方法,例如谢谢,但我试图理解,这不能通过和EventTrigger实现吗?