按钮的IsEnabled绑定不正常工作

11

Button.IsEnabled不能正常工作。

我已经调试了代码,并且该属性的setter方法被"true"值访问。但是按钮仍然被禁用。

View.xaml:

<StackPanel Grid.Row="2" Margin="0,20,0,0" >
        <Button Name="ButtonOk" Content="OK" Margin="0,0,4,0" IsEnabled="{Binding SomethingIsValid}"  Command="{Binding CommandOk}" />
        <Button Name="ButtonCancel" Content="Cancel" Margin="0,0,4,0" IsCancel="True" /
</StackPanel>

View.xaml.cs:

...
public View(ViewModel viewModel)
{
    this.InitializeComponent();

    this.viewModel = viewModel;
    this.DataContext = viewModel;            
}

视图模型:

public bool SomethingIsValid
{
   get
   {
      return somethingIsValid;
   }
   set
   {
      this.somethingIsValid= value;
      this.RaisePropertyChanged(() => this.SomethingIsValid);
   }
}

#region IDataErrorInfo
public string this[string columnName]
{
   get
   {
      this.SomethingIsValid= false;

      if ("SomeName" == columnName)
      {
         if (string.IsNullOrEmpty(this.Status))
         {
            return "Please bla bla..";
         }
      }

      this.SomethingIsValid = true;
      return string.Empty;
   }
}

public string Error
{
   get
   {
      return string.Empty;
   }
}
#endregion

public ICommand CommandOk
{
   get
   {
      if (this.commandOk == null)
      {
         this.commandOk = new RelayCommand(this.CommandOkAktion, () => this.SomethingIsValid );
      }

      return this.commandOk;
   }
}

2
你能展示一下你的命令:“CommandOk”吗?通常情况下,按钮的启用和禁用是由绑定命令中定义的“CanCommandExecute”控制的。 - Bolu
1
正如@Bolu所建议的那样,可能是您的命令禁用了按钮(ICommand接口具有CanExecute方法:如果返回false,则绑定到该命令的按钮将被禁用)。 - Steven Rands
@Bolu 命令已确认,调用模型并将信息存储在数据库中。 - MikroDel
@Bolu - 抱歉,之前提供了错误的信息 - 我现在会发布代码。 - MikroDel
@Bolu - 我已经更新了我的问题,加入了命令。 - MikroDel
7个回答

30

如果任何人仍然遇到问题 - 确保您的IsEnabled属性在Command属性之后。

<Button Command="{Binding StartCommand}" IsEnabled="{Binding StartEnabled}" />

- 工作

  <Button IsEnabled="{Binding StopEnabled}" Command="{Binding StopCommand}"  />

- 不起作用

请注意,我的两个命令始终可以执行。这对我来说是一个更简单的解决方案。


3
这对我来说是最简单的答案,应该在某个地方列出作为同时使用Command属性和IsEnabled属性的“陷阱”。 - Josh Feldman
4
这对我也起作用,但似乎真的是一个应该被修复的错误 :-) - mike gold
这是正确的答案!唯一无二的。 - Zi Cold
3
2021年,我认为这个不再起作用了。 - user1034912
通常的 Xamarin... 我简直不敢相信我浪费了半个小时在这上面... 我的问题是我将它绑定到一个复选框并且一开始启用... 而复选框没有被选中... 然后点击两次复选框并且禁用它... - George B
显示剩余3条评论

23
如果您正在使用命令,单独绑定按钮的IsEnabled属性并不是一个好主意。相反,您应该在命令的"CanExecute"中提供正确的值来启用按钮。

谢谢您的回复!我已经点赞 :) 我已经调试过了,CanExecute(true) 已经显示。 - MikroDel
我不知道你具体指的是什么。这个方法 public bool CanExecute(object parameter) { return this.canExecute == null || this.canExecute(); } 被调用了。 - MikroDel
@MikroDel,在你的情况下,你只是绑定到一个属性,这并不太重要(仍然是重复的)。CanExecute是一个函数,可以带参数,因此在其他情况下它将更加有用。 - Bolu
https://dev59.com/2WDVa4cB1Zd3GeqPe5ha - Martin Moser
2
为什么这会是一个更好的想法呢?有些情况下,其他事件需要禁用此按钮。因此,我们将始终拥有一个布尔值。将此布尔值绑定是否更加简洁? - Neville Nazerane
显示剩余3条评论

2
如果您正在使用RelayCommand,您可以使用第二个参数作为布尔方法,该方法指示命令是否可以执行:
public RelayCommand(Action execute, Func<bool> canExecute);

使用方法:

this.DetermineCommand = new RelayCommand(this.Determine, () => this.IsValid);

1
根据您发布的代码,我所能看到的是,如果没有任何调用“this [SomeName]”,那么您的“SomethingIsValid”将始终为“false”,这就是为什么您的按钮显示为“disabled”的原因。因此,我的建议/解决方案是:

从xaml中删除IsEnabled绑定(如果您的Command绑定正常工作,则不需要此绑定):

<StackPanel Grid.Row="2" Margin="0,20,0,0" >
    <Button Name="ButtonOk" Content="OK" Margin="0,0,4,0" Command="{Binding CommandOk}" />
    <Button Name="ButtonCancel" Content="Cancel" Margin="0,0,4,0" IsCancel="True" /
 </StackPanel> 

将您的ViewModel代码更改为以下内容(您当前的Command定义是可以的,因此不需要更改该部分)。下面的代码确保在执行 CanCommandExecute 时,它会重新检查 SomethingIsValid
public bool SomethingIsValid
{
   get
   {
      return string.IsNullOrEmpty(Error);
   }
}

public string this[string columnName]
{
   get
   {
      switch(columnName)
      {
          case "SomeName":
          {
               if (string.IsNullOrEmpty(this.Status))
               {
                  return "Please bla bla..";
               }
               break;
          }
          case "SomeOtherName":
          {
               if (string.IsNullOrEmpty(this.OtherProperty))
               {
                  return "Please bla bla..";
               }
               break;
          }

      }
      return string.Empty;         

   }
}

public string Error
{
   get
   {
      return this["SomeName"]+this["SomeOtherName"];
   }
}
#endregion

这样,用户将不会看到灰色的“确定”按钮(禁用状态)。我想避免它被点击。 - MikroDel
@MikroDel,这不应该发生,因为当this.Status为空或null时,SomethingIsValid将返回false。请进行一些调试。 - Bolu
这就像是一条建议 - 使用谷歌或阅读MSDN。我已经发布了我的代码,希望能在我错过明显的东西时得到帮助。 - MikroDel
我没有找到使用IsEnabled和Command组合的信息是一种不好的做法。 - MikroDel
@MikroDel,我更新了我的答案,你可以将其添加到你的IDataErrorInfo区域中。 - Bolu
显示剩余5条评论

0
如果你使用命令像这样:
[RelayCommand]
async Task Refresh()
{
    await LoadListAsync();
}

然后,您可以将您的布尔值作为参数传递给Relay属性,如下所示:
[RelayCommand(CanExecute = nameof(CanRefresh))]
async Task Refresh()
{
    await LoadListAsync();
}

请参考MAUI文档以获取更详细的信息。

0

我认为 OP 已经完成了这个操作:this.RaisePropertyChanged(() => this.SomethingIsValid); - Bolu
谢谢您的回复!Bolu是正确的 - 我已经实现了它并调用了它。 - MikroDel
是的,我确实是新来的...第一课:在回答之前更仔细地阅读代码示例。 - Robin

-3

我通过绑定IsEnabled的值来解决了这个问题。明确将其设置为False并没有起作用。

这个方法有效:

<Button Text="Login" Command="{Binding LoginCommand}" IsEnabled="{Binding ButtonsEnabled}" />

这个没有起作用:

<Button Text="Login" Command="{Binding LoginCommand}" IsEnabled="False" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接