RelayCommand CanExecute 行为不起作用

发布于 2024-09-24 09:00:31 字数 2099 浏览 1 评论 0原文

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

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

我想知道 lambda 是否无法正确用于 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 时,它开始禁用并正确启用已设置。我想我应该记住不要修理没有损坏的东西!

I'm having trouble getting the RelayCommand to enable/disable the attached control properly.

I've got an EventToCommand element attached to a button. The command is databound to the ViewModel. Initially, the button is disabled (expected behavior), but I cannot seem to get the CanExecute logic to check it's value. When CurrentConfigFile is set and exists, the button should be enabled. I've executed code and checked the file's value in debug to make sure it's set, but the control is still disabled. I've tried CommandManager.InvalidateRequerySuggested() and command.RaiseCanExecuteChanged(), but it will not enable.

I've wondered if lambdas don't work correctly for the CanExecute behavior (even though the examples use them) or that the CanExecute behavior needs to be databound to another element.

Here's my code:

// 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);

}

and markup

<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>

Update:

As per Isak Savo's suggestion, I bound the RelayCommand directly to the button with

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

and it started disabled and correctly enabled when the FileInfo was set. Guess I should remember not to fix what isn't broken!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暖树树初阳… 2024-10-01 09:00:31

为什么不直接从按钮绑定到命令?

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

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

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

:正如评论中指出的,OP已经尝试过命令管理器方法。

Why don't you just bind to the Command directly from the Button?

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

Maybe the EventToCommand thing you are using is messing things up with the command's CanExecute notification.

And regarding the CanExecute problem - are you sure that your CanExecute handler is called after the CurrentConfigFile property is set? I've found that even though WPF mostly does a good job of requerying CanExecute, I still sometimes need to force a requery through the CommandManager.

EDIT: As pointed out in the comments, the OP has already tried the command manager approach.

洛阳烟雨空心柳 2024-10-01 09:00:31

msdn 中写道:

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

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

In msdn is written:

When first called, FileInfo calls Refresh and caches information about the file. On subsequent calls, you must call Refresh to get the latest copy of the information.

However, I would not do such a check in the CanExecute-handler. This may slow down your UI because CanExecute is called a lot of times and I could imagine that such IO-checks can become slow, for example if the file lies on a network share.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文