我试图找到一个关于如何将一些TextBox事件(PreviewTextInput和PreviewKeyDown)绑定到命令的简单示例,但是我找不到任何明确的示例,到目前为止我发现的所有exmap都强制我使用一些MVVM框架(Light toolkit,Prism等),但是目前我不想使用框架,因为我想更深入地了解业务的运作方式。
提前致谢。
答案 0 :(得分:-1)
您可以继承TextBox并实施ICommandSource。我做了同样的事情,我的实现看起来像这样。您应该能够将其扩展为在PreviewTextInput上工作。
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;
}
}
答案 1 :(得分:-1)
简单的方法是在XAML中为事件附加公共事件处理程序,并在代码隐藏中调用Command。这样的事件处理程序可能如下所示:
private void TextBox_OnTextChanged(object sender, EventArgs e)
{
var viewmodel = this.DataContext as MyViewmodel;
if (viewmodel != null)
{
viewmodel.SomeCommand.Execute();
}
}
在代码隐藏中没有任何代码的情况下运行的替代方案(但实现起来有点棘手,仅适用于.NET 4.5)是实现自己的MarkupExtension,这样就可以编写类似
的代码<TextBox TextChanged="{myMarkupExtension:CommandBinding SomeCommand]">...</TextBox>
有一些文章描述了这种方法,例如this one