【问题标题】:RelayCommand CanExecute behavior not workingRelayCommand CanExecute 行为不起作用
【发布时间】:2010-09-20 20:16:24
【问题描述】:

我无法让RelayCommand 正确启用/禁用附加的控件。

我在按钮上附加了一个 EventToCommand 元素。该命令数据绑定到 ViewModel。最初,该按钮被禁用(预期行为),但我似乎无法获得 CanExecute 逻辑来检查它的值。当CurrentConfigFile 设置并存在时,应启用该按钮。我已经执行了代码并在调试中检查了文件的值以确保它已设置,但控件仍然被禁用。我试过CommandManager.InvalidateRequerySuggested()command.RaiseCanExecuteChanged(),但它不会启用。

我想知道 lambdas 是否不能正常工作于 CanExecute 行为(即使示例使用了它们),或者 CanExecute 行为需要数据绑定到另一个元素。

这是我的代码:

// The FileInfo being checked for existence before the button should be enabled
public const string CurrentConfigFilePN = "CurrentConfigFile";
public FileInfo CurrentConfigFile
{
    get
    {
        return _currentConfigFile;
    }

    set
    {
        if (_currentConfigFile == value)
        {
            return;
        }

        var oldValue = _currentConfigFile;
        _currentConfigFile = value;

        // Update bindings, no broadcast
        RaisePropertyChanged(CurrentConfigFilePN);
    }
}

public MainViewModel()
{
    // snip //

    SaveCommand = new RelayCommand(SaveConfiguration, 
        () => CurrentConfigFile != null && CurrentConfigFile.Exists);
    }

private void SaveConfiguration()
{

    // export model information to xml document
    ExportXMLConfiguration(CurrentConfigFile);

}

和标记

<Button x:Name="SaveButton" Content="Save" Width="75" Margin="20,5">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <GalaSoft:EventToCommand x:Name="SaveETC" 
                Command="{Binding SaveCommand}" 
                MustToggleIsEnabledValue="true" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

更新:

根据 Isak Savo 的建议,我将 RelayCommand 直接绑定到按钮上

<Button x:Name="SaveButton" Content="Save" Width="75" Margin="20,5" 
Command="{Binding SaveCommand}"/>

当设置FileInfo 时,它开始禁用并正确启用。猜猜我应该记住不要修复没有损坏的东西!

【问题讨论】:

    标签: c# wpf mvvm-light


    【解决方案1】:

    为什么不直接从 Button 绑定到 Command 呢?

    <Button Command="{Binding SaveCommand}" Content="Save" />
    

    也许您正在使用的 EventToCommand 将命令的 CanExecute 通知搞砸了。

    关于 CanExecute 问题 - 你确定你的 CanExecute 处理程序是在设置 CurrentConfigFile 属性之后调用的吗?我发现尽管 WPF 在重新查询 CanExecute 方面做得很好,但有时我仍然需要通过 CommandManager 强制重新查询。

    编辑:正如 cmets 中所指出的,OP 已经尝试了命令管理器方法。

    【讨论】:

    • 他在问题中写道,他调用了 CommandManager.InvalidateRequerySuggested()。这就是为什么我认为他应该看看 RelayCommand。
    • @HCL:我傻了,我应该更仔细地阅读原始问题:-)
    • 我会看看那个。 EventToCommand 元素是 MVVM-light(已标记)的一部分,这就是我尝试使用它的原因。它对于保持以 MVVM 为中心非常有用,除了看起来相当明显的问题。感谢您的输入!我会继续努力的。
    • 我的意思是,它绝对不会增加任何东西。按钮上的 Command 属性会(在内部)在单击时做出反应,因此您不会从使用 EventToCommand 中获得任何收益。它存在的原因是当控件没有命令属性时,或者您想在其他事件上执行命令
    • 抱歉回复晚了。我明白你的意思,EventToCommand 控件如何不添加任何 ButtonBase 内部无法处理的内容。我会尝试删除EventToCommand,看看它的行为是否不同。感谢您指出这一点!
    【解决方案2】:

    msdn 中写着:

    第一次调用时,FileInfo 调用 Refresh 并缓存有关文件的信息。在后续调用中,您必须调用 Refresh 以获取信息的最新副本。

    但是,我不会在 CanExecute 处理程序中进行这样的检查。这可能会减慢您的 UI,因为 CanExecute 被调用了很多次,我可以想象这样的 IO 检查可能会变慢,例如,如果文件位于网络共享上。

    【讨论】:

    • 有趣的一点,我很高兴你提出来(主要是因为我不知道)。但是,即使在我将刷新添加到 getter 之后(由于性能问题,您建议不要这样做),行为也没有改变。即使Exists 为真,该按钮也不会启用。
    • 您的中继命令如何处理 CanExecuteChanged 事件?本次活动如何整合?也许错误就在那里。
    • 我使用的是 MVVM-light 框架,所以框架中内置了 RelayCommand 类。 (不?)幸运的是,Laurent Bugnion 决定在 SO 上众包对框架的支持,这就是我在这里问这个问题的原因。我将尝试查看 MVVM-light 的源代码以获取更多信息。
    • MVVM-light 在 RelayCommand 上有一个名为 RaiseCanExecuteChanged 的​​方法。当你想重新检查按钮/元素是否应该启用/禁用时,你可以调用它。
    猜你喜欢
    • 2013-02-10
    • 2011-01-19
    • 2014-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    相关资源
    最近更新 更多