【发布时间】:2014-12-10 20:13:54
【问题描述】:
我创建了一个实现 ICommandSource 的 TextBox,在大多数情况下,我使用 Slider 遵循 Microsoft 的示例。此文本框将在按下“Enter”键时执行绑定命令。这部分行为正常工作,我遇到的问题是 IsEnabled 不能再在 XAML 中设置?我不确定这是为什么,您仍然可以在 Button 等原生 Microsoft 类上设置 IsEnabled。
public class CommandTextBox : TextBox, ICommandSource
{
// The DependencyProperty for the Command.
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandTextBox), new PropertyMetadata(OnCommandChanged));
// The DependencyProperty for the CommandParameter.
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(CommandTextBox));
// The DependencyProperty for the CommandTarget.
public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(CommandTextBox));
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public object CommandParameter
{
get { return GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public bool CommandResetsText { get; set; }
public IInputElement CommandTarget
{
get { return (IInputElement)GetValue(CommandTargetProperty); }
set { SetValue(CommandTargetProperty, value); }
}
// Command dependency property change callback.
private static void OnCommandChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
CommandTextBox ctb = (CommandTextBox)dp;
ctb.HookUpCommand((ICommand)e.OldValue, (ICommand)e.NewValue);
}
// Add a new command to the Command Property.
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);
}
// Remove an old command from the Command Property.
private void RemoveCommand(ICommand command)
{
EventHandler handler = CanExecuteChanged;
command.CanExecuteChanged -= handler;
}
// Add the command.
private void AddCommand(ICommand command)
{
var handler = new EventHandler(CanExecuteChanged);
canExecuteChangedHandler = handler;
if (command != null)
command.CanExecuteChanged += canExecuteChangedHandler;
}
private void CanExecuteChanged(object sender, EventArgs e)
{
if (Command != null)
{
RoutedCommand command = Command as RoutedCommand;
// If a RoutedCommand.
if (command != null)
{
if (command.CanExecute(CommandParameter, CommandTarget))
this.IsEnabled = true;
else
this.IsEnabled = false;
}
// If a not RoutedCommand.
else
{
if (Command.CanExecute(CommandParameter))
this.IsEnabled = true;
else
this.IsEnabled = false;
}
}
}
// If Command is defined, pressing the enter key will invoke the command;
// Otherwise, the textbox will behave normally.
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.Key == Key.Enter)
{
if (Command != null)
{
RoutedCommand command = Command as RoutedCommand;
if (command != null)
command.Execute(CommandParameter, CommandTarget);
else
Command.Execute(CommandParameter);
if (CommandResetsText)
this.Text = String.Empty;
}
}
}
private EventHandler canExecuteChangedHandler;
}
XAML
<Button Command="{Binding GenericCommand}" IsEnabled="False" /> // This is disabled(desired).
<CommandTextBox Command="{Binding GenericCommand}" IsEnabled="False" /> // This is enabled?
我们将不胜感激。
【问题讨论】:
-
“不能再设置”?你对此有何假设?每次调用
CanExecuteChanged时,您都会在代码中设置IsEnabled,因此您在 XAML 中设置的任何值都会在您启动应用程序时立即被覆盖...... -
@Patrick 我已经包含了一些 XAML 来显示这个问题,我希望 CommandTextBox 的 IsEnabled 实现能够反映 Button 的实现。
-
@FrumRoll
IsEnabled在CanExecuteChanged处理程序中被覆盖。可能您的命令调用 CanExecuteChanged。您最好在CanExecuteChanged上设置断点并查看整个堆栈跟踪以找到原因。 -
@EldarDordzhiev 你是对的,CanExecuteChanged 处理程序覆盖了 IsEnabled。最好问我的问题,我的实现与 Button 中的实现有何不同?如何解决这种行为差异?
-
@FrumRoll 好的,我知道了,检查下面的答案。