我正在尝试使用一些命令来创建一个用户控件。如果我用这里所示的http://msdn.microsoft.com/en-us/library/vstudio/ms771361(v=vs.90).aspx方法连接xaml中的命令,它就能工作,但是如果我使用来自棱镜库的DelegateCommand,CanExecuteChanged不会对用户控件开火,我也不知道为什么。我很抱歉我意识到这是很多代码。正确执行激发,但CanExecute从不执行。
提前谢谢。
自定义控件Xaml
<UserControl x:Class="Controls.LinkButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TextBlock>
<Hyperlink x:Name="hyperLink" Click="Hyperlink_Click">
<Run x:Name="textRun"
Text="Click Me"/>
</Hyperlink>
</TextBlock>
</UserControl>自定义控制代码在后面
public partial class LinkButton : UserControl, ICommandSource
{
public LinkButton()
: base()
{
InitializeComponent();
textRun.DataContext = this;
hyperLink.DataContext = this;
}
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(LinkButton), new PropertyMetadata(null, new PropertyChangedCallback(CommandChanged)));
public object CommandParameter
{
get { return (object)GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register("CommandParameter", typeof(object), typeof(LinkButton), new PropertyMetadata(null));
public IInputElement CommandTarget
{
get { return (IInputElement)GetValue(CommandTargetProperty); }
set { SetValue(CommandTargetProperty, value); }
}
public static readonly DependencyProperty CommandTargetProperty =
DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(LinkButton), new PropertyMetadata(null));
private void Hyperlink_Click(object sender, RoutedEventArgs e)
{
if (Command != null)
{
RoutedCommand command = Command as RoutedCommand;
if (command != null)
{
command.Execute(CommandParameter, CommandTarget);
}
else
{
((ICommand)Command).Execute(CommandParameter);
}
}
}
public static EventHandler canExecuteChangedHandler;
private static void CommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
LinkButton lb = (LinkButton)d;
lb.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, newCommand);
}
AddCommand(oldCommand, newCommand);
}
// Remove an old command from the Command Property.
private void RemoveCommand(ICommand oldCommand, ICommand newCommand)
{
EventHandler handler = CanExecuteChanged;
oldCommand.CanExecuteChanged -= handler;
}
// Add the command.
private void AddCommand(ICommand oldCommand, ICommand newCommand)
{
EventHandler handler = new EventHandler(CanExecuteChanged);
canExecuteChangedHandler = handler;
if (newCommand != null)
{
newCommand.CanExecuteChanged += canExecuteChangedHandler;
}
}
private void CanExecuteChanged(object sender, EventArgs e)
{
if (this.Command != null)
{
RoutedCommand command = this.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;
}
}
}
}
}窗口
<ctrl:LinkButton Command="{Binding LinkClicked}"/>
public partial class MainWindow : Window
{
public MainWindow()
{
LinkClicked = new DelegateCommand(DoSomething, CanDoSomething);
InitializeComponent();
DataContext = this;
LinkClicked.RaiseCanExecuteChanged();
}
public DelegateCommand LinkClicked { get; set; }
public void DoSomething()
{
MessageBox.Show("Did Something");
}
public bool CanDoSomething()
{
return false;
}
}发布于 2014-08-15 17:11:13
这里的问题是您正在调用LinkClicked.RaiseCanExecuteChanged();在设置DataContext之后,在此之前,LinkedCommand没有绑定,因此DelegateCommand的CanExecuteChanged事件为null,因此RaiseCanExecuteChanged()不会做任何事情。因此,为了避免在加载的窗口事件中调用LinkClicked.RaiseCanExecuteChanged(),在此之前绑定将被更新。虽然这是一个很脏的解决方案,因为您必须在任何地方都这样做,在这里您将使用这个LinkButton并绑定它的命令。
RaiseCanExecuteChanged的实现如下所示
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null) //CanExecuteChanged is coming null in your case so the event is not fired.
CanExecuteChanged(this, new EventArgs());
}或者更好的解决方案是在CanExecute方法中没有调用AddCommand,在实际的命令实现中调用CanExecute
if (newCommand != null)
{
newCommand.CanExecuteChanged += CanExecuteChanged;
newCommand.CanExecute(CommandParameter); //you are missing this.
}如果这样做,就没有必要调用RaiseCanExecuteChanged。
https://stackoverflow.com/questions/25330223
复制相似问题