可以访问其目标的WPF Command

时间:2016-03-08 16:58:53

标签: wpf icommand

我想在WPF中编写一个命令,我可以在多个地方使用它来对文本框中的文本执行操作。让我们说这个命令的目的是通过在它的任一侧添加星号来 Bold 一些文本。该命令将添加到上下文菜单中并定位文本框。

以下是问题:

  • 我如何知道目标是哪个文本框? ICommand不包含CommandTarget。

  • 如何响应文本框中的更改(例如,是否选择了任何文本)以引发CanExecuteChanged?我知道我可以使用CommandManager.RequerySuggested事件,但是有更有效的方法吗?

以下是我对XAML的看法:

    <TextBox Name="TargetTextBox">
        <TextBox.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Bold" Command="{x:Static Commands.MyBoldCommand}" CommandTarget="{Binding ElementName=TargetTextBox}" />
            </ContextMenu>
        </TextBox.ContextMenu>
    </TextBox>

2 个答案:

答案 0 :(得分:2)

您可以通过CommandParameter传入FontWeight来访问它。这是一个例子:

<强> XAML:

<TextBox>
    <TextBox.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Bold" Command="{Binding MyCommand}" CommandParameter="{Binding Path=PlacementTarget.FontWeight, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
        </ContextMenu>
    </TextBox.ContextMenu>
</TextBox>

<强>的ICommand:

public ICommand MyCommand
{
    get
    {
        if (_MyCommand == null)
        {
            _MyCommand = new RelayCommand(
                param => this.MyCommandFunction(param)
                );
        }
        return _MyCommand;
    }
}

<强> MyCommandFunction:

private void MyCommandFunction(object param)
{
    FontWeight fw = (FontWeight)param;
    fw = FontWeights.Bold; 
}

我刚刚使用了一个RelayCommand,但是你可以使用DelegateCommand。你必须像这样绑定命令参数,以便菜单项的datacontext在文本框上有一个可视化。在它的正常范围内,它没有。您仍然需要更新视图。

答案 1 :(得分:0)

这是我用于继承自ICommand的通用CommandBase的内容:

/// <summary>
/// Base class for all Commands.
/// </summary>
public abstract class CommandBase : ICommand
{
    /// <summary>
    /// Defines the method that determines whether the command can execute in its current 
    /// state.
    /// </summary>
    /// <param name="parameter">Data used by the command.  If the command does not require data 
    /// to be passed, this object can be set to null.</param>
    /// <returns>
    /// true if this command can be executed; otherwise, false.
    /// </returns>
    public virtual bool CanExecute(object parameter) 
    {
        return true;
    }

    /// <summary>
    /// Defines the method to be called when the command is invoked.
    /// </summary>
    /// <param name="parameter">Data used by the command.  If the command does not require data 
    /// to be passed, this object can be set to null.</param>
    public abstract void Execute(object parameter);

    /// <summary>
    /// Occurs when changes occur that affect whether or not the command should execute.
    /// </summary>
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
}

以下是我推荐的步骤:

  1. 在ViewModel中指定字符串属性( MyTextProperty )以处理文本框文本。
  2. 创建一个继承自上述 CommandBase 的命令( MyTextChangedCommand ),该命令带有ViewModel类型的参数( YourViewModelType )。然后通过访问传递给您命令的ViewModel直接与 MyTextProperty 进行交互,而不是尝试使用CommandParameters。
  3. 在ViewModel中创建一个 MyTextChangedCommand 类型的属性,并确保在ViewModel的构造函数中实例化它。
  4. 对于WPF中的命令绑定,我会使用Blend Interactivity for WPF v4.0

    以下是如何实现TextBox(假设您引用Microsoft.Expression.Interactions为&#34; i&#34;:

    <TextBlock Text="{Binding Path=MyTextProperty">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="LostFocus">
                <i:InvokeCommandAction 
                    Command="{Binding Path=MyTextChangedCommand}"
                    CommandParameter="Whatever" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TextBlock>