更新标题:为什么 ICommand.CanExecute 一直被调用,而不是像事件一样工作? [英] Updated title: Why ICommand.CanExecute is getting called all the time, instead of working like an event?

查看:75
本文介绍了更新标题:为什么 ICommand.CanExecute 一直被调用,而不是像事件一样工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 WPF 中采用了 MVVM 模式并且已经学会了 Command 的使用.但是在我的实现中,我分配给实现 CanExecute 的委托总是被调用.我的意思是,如果我在委托函数中放置一个断点,则表明该函数不断被调用.根据我的理解(以及一种自然的思维方式,但当然我可能是错的),只有当我以某种方式通知状态更改时才会调用此委托,并且 CommandManager(重新)检查CanExecute 属性并修改 UI 元素的 IsEnabled 属性.

I am adopting MVVM pattern in WPF and have learned the use of Command. But in my implementation, the delegate I assigned to implement CanExecute is always called. I mean if I put a break point inside the delegate function, it shows that this function keeps getting called. To my understanding (and a natural way of thinking, but of course I can be wrong), this delegate only gets called when I somehow notifies the change of the state and that's when the CommandManager (re)checks the CanExecute property and modify the IsEnabled property of the UI element.

这是我的 VB.NET 实现,它最初来自 C# 版本.我确实注意到我需要对移植的代码进行一些更改才能编译.会不会是C#和VB.NET的底层不一样?那么有人可以为我提供一个原始的 VB.NET 实现,或者指出我有什么问题,或者如果我正确理解命令行为,该怎么办?

Here is my implementation of VB.NET, which I got originally from a C# version. I did notice that I needed to make some change to the ported code in order for it to compile. Could it be the underlying of C# and VB.NET is different? So can somebody provide me a original VB.NET implementation, or point me out what is wrong or do if I understand the Command behavior correctly?

这是我的 VB.NET 版本:

Here is my VB.NET version:

 Public Class CommandBase
    Implements ICommand

    Public Property ExecuteDelegate() As Action(Of Object)

    Public Property CanExecuteDelegate() As Predicate(Of Object)

    Public Sub New()
    End Sub

    Public Sub New(execute As Action(Of Object))
        Me.New(execute, Nothing)
    End Sub

    Public Sub New(execute As Action(Of Object), canExecute As Predicate(Of Object))
        If execute Is Nothing Then
            Throw New ArgumentNullException("execute")
        End If
        ExecuteDelegate = execute
        CanExecuteDelegate = canExecute
    End Sub

    Public Function CanExecute(parameter As Object) As Boolean Implements ICommand.CanExecute
        Return If(CanExecuteDelegate Is Nothing, True, CanExecuteDelegate(parameter))
    End Function

    Public Custom Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged
        AddHandler(ByVal value As EventHandler)

            If CanExecuteDelegate IsNot Nothing Then
                AddHandler CommandManager.RequerySuggested, value
            End If

        End AddHandler
        RemoveHandler(ByVal value As EventHandler)
            If CanExecuteDelegate IsNot Nothing Then
                RemoveHandler CommandManager.RequerySuggested, value
            End If
        End RemoveHandler

        RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
            CommandManager.InvalidateRequerySuggested()
        End RaiseEvent
    End Event

    Public Sub Execute(parameter As Object) Implements ICommand.Execute
        If ExecuteDelegate IsNot Nothing Then ExecuteDelegate.Invoke(parameter)
    End Sub

    Public Sub RaiseCanExecuteChanged()
        CommandManager.InvalidateRequerySuggested()
    End Sub

End Class

我如何实例化一个对象是这样的:

And how I instantiate an object is something like this:

MyCommand = New CommandBase(AddressOf CommandExec, AddressOf CanExecuteExec)

其中 CanExecuteExec 当然有这样的签名:

where the CanExecuteExec of course has the signature like this:

Private Function CanExecuteExec(obj As Object) As Boolean

就像我提到的,CanExecuteExec 一直在被调用.我想这是低效的,想象一下我有数百个 Command 对象,其中大部分 CanExecute 大部分时间都不会改变.

Like I mentioned, the CanExecuteExec is getting called all the time. I guess it is inefficient, imagine that I have hundreds of Command objects and most of the CanExecute of them don't get changed most of the time.

有人说 CanExecute 确实一直被调用,而其他人则相反.我不是这方面的专家,但我不得不说第二种意见听起来更自然,对我来说更有意义.虽然我仍然需要弄清楚这是否属实,但为什么 WPF 一直检测更改以便它不断检查 CanExecute

Somebody says the CanExecute indeed gets called all the time, while others say the opposite. I am no expert on this but I have to say the second opinion sounds more natural and makes more sense to me. Although I still need to figure out if that is true, why WPF detects the change all the time so that it keeps checking the CanExecute

推荐答案

在您的 CanExecuteDelegate 中,您可以连接到 CommandManager.RequerySuggested.

In your CanExecuteDelegate you have hook to CommandManager.RequerySuggested.

因此,每当 CommandManager.RequerySuggested 引发您的 CanExecuteDelegate 将被调用.

So, whenever CommandManager.RequerySuggested is raised your CanExecuteDelegate will be called.

CommandManager.RequerySuggested 事件在命令检测到命令源更改时引发管理器,范围从 Keyboard.KeyUpEventMouse.ClickEvent

CommandManager.RequerySuggested event is raised whenever changes to the command source are detected by the command manager which ranges from Keyboard.KeyUpEvent, Mouse.ClickEvent etc.

此外,CommandManager 有一个静态方法 - InvalidateRequerySuggested,它强制 CommandManager 引发 RequerySuggestedEvent.因此,您也可以调用它来手动验证您的命令.

Also, CommandManager has a static method - InvalidateRequerySuggested which forces the CommandManager to raise the RequerySuggestedEvent. So, you can call that to validate your commands too manually.

如果您想掌握提高 CanExecute 的控制权,您可以使用 委托命令 由 PRISM 提供.CanExecute 委托仅在您显式调用由委托命令公开的 RaiseCanExecuteChanged() 方法时才会被调用.

If you want to take the control in hand for raising CanExecute, you can use the Delegate Command provided by PRISM. CanExecute delegate will get called only when you explicitly call RaiseCanExecuteChanged() method exposed by Delegate Command.

加入评论以回答

自从转向 VS 以来,每次都会遇到断点CommandManager RequerySuggested 事件在失去焦点时被调用窗口和激活属性更改的窗口.这就是为什么你请注意,当您移动到VS 因为焦点从 WPF 窗口移动到 Visual Studio.

Breakpoint is hitting every time on turning to VS since CommandManager RequerySuggested event gets called on lost focus of window and on activation property changed of window. That's why you notice that breakpoint is hitting every now and then when you move to VS since focus moves from WPF window to Visual Studio.

这篇关于更新标题:为什么 ICommand.CanExecute 一直被调用,而不是像事件一样工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆