WPF ICommands 绑定

WPF ICommands Binding

我将继续探索 WPF 并尝试使用命令来遵循 MVVM。 我的简单代码如下。

MainWindow.xaml

<Window x:Class="ClickCommand.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ClickCommand"
        xmlns:vm="clr-namespace:ClickCommand.ViewModel"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    
    <Window.Resources>
        <vm:ButtonViewModel x:Key="ViewModel"/>
    </Window.Resources>
    <Grid>
        <StackPanel Width="350" HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Vertical">
            <Button Height="80" FontSize="32" Background="LightBlue" Content="Click Me"
                    Command="{Binding ButtonCommand, Source={StaticResource ViewModel}}"/>
            <TextBox x:Name="textBoxTest" Margin="5" FontSize="36"/>
            <Button Height="80" FontSize="32" Background="LightBlue" Content="Click if TextBox as Text"
                    Command="{Binding ButtonParameterCommand, Source={StaticResource ViewModel}}" CommandParameter="{Binding Text, ElementName=textBoxTest}"/>
        </StackPanel>
    </Grid>
</Window>

ButtonViewModel.cs

public ButtonViewModel()
{
    ButtonCommand = new ButtonCommand();
    ButtonParameterCommand = new ButtonParameterCommand();
}

public ICommand ButtonCommand { get; }
public ICommand ButtonParameterCommand { get; }

CommandBase.cs

abstract class CommandBase : ICommand
{
    public event EventHandler CanExecuteChanged;

    public virtual bool CanExecute(object parameter)
    {
        return true;
    }

    public abstract void Execute(object parameter);

    protected void OnCanExecutedChanged()
    {
        CanExecuteChanged?.Invoke(this, new EventArgs()); 
    }
}

ButtonCommand.cs

public override void Execute(object parameter)
{
    MessageBox.Show("Button is Clicked");
}

ButtonParameterCommand.cs

public override bool CanExecute(object parameter)
{
     return true;
}
public override void Execute(object parameter)
{
    MessageBox.Show(parameter as string);
}

我的问题是,如果 IsNullOrEmpty 上方的文本框,我想禁用第二个按钮,但是我认为可以解决此问题的代码会使该按钮永久禁用。我一直在尝试的代码是`

public override bool CanExecute(object parameter)
{
      if (parameter != null)
      {
          if (String.IsNullOrEmpty(parameter as string))
          {
              return false;
          }
          else
          {
              return true;
          }
      }
      return false;
  }

这是我的错误还是Xaml绑定?我希望有人能提供帮助,并在此先感谢您的帮助。`

每当 TextBox 中的文本更改时,您需要引发命令的 CanExecuteChanged 事件。

创建 CommandBase class publicOnCanExecutedChanged() 方法,并从您使用的来源 属性 的 setter 调用它将 TextBox 绑定到:

public class ButtonViewModel
{
    public ButtonViewModel()
    {
        ButtonCommand = new ButtonCommand();
        ButtonParameterCommand = new ButtonParameterCommand();
    }

    private string _text;
    public string Text
    {
        get { return _text; }
        set 
        { 
            _text = value;
            ButtonParameterCommand.OnCanExecutedChanged();
        }
    }

    public ICommand ButtonCommand { get; }
    public CommandBase ButtonParameterCommand { get; }
}

XAML:

<TextBox x:Name="textBoxTest" Margin="5" FontSize="36"
         Text="{Binding Text, Source={StaticResource ViewModel}}"/>

但是你真的应该研究如何实现接受 Action<object>Predicate<object> 的“中继”或“委托”命令,并在 [=20] 的实现中调用它们=] 和 CanExecute 方法。