更新的标题:为什么 ICommand.CanExecute 一直被调用,而不是像事件一样工作?

2024-04-15

我在 WPF 中采用 MVVM 模式并学习了使用Command。但在我的实现中,我分配来实现的代表CanExecute总是被调用。我的意思是,如果我在委托函数内放置一个断点,它表明该函数不断被调用。根据我的理解(也是一种自然的思维方式,但我当然可能是错的),只有当我以某种方式通知状态发生变化时,才会调用该代表,而此时CommandManager(重新)检查CanExecute属性并修改IsEnabledUI 元素的属性。

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

这是我的 VB.NET 版本:

 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

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

MyCommand = New CommandBase(AddressOf CommandExec, AddressOf CanExecuteExec)

其中 CanExecuteExec 当然具有如下签名:

Private Function CanExecuteExec(obj As Object) As Boolean

正如我提到的,CanExecuteExec一直被打电话。我想这效率很低,想象一下我有数百个Command对象和大多数CanExecute其中大部分时间都不会改变。

UPDATE:

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


In your CanExecuteDelegate你有钩子CommandManager.RequerySuggested.

所以,每当CommandManager.RequerySuggested http://msdn.microsoft.com/en-us/library/system.windows.input.commandmanager.requerysuggested.aspx提高了你的CanExecuteDelegate将被调用。

每当命令检测到命令源发生更改时,都会引发 CommandManager.RequerySuggested 事件 经理的范围从键盘.KeyUpEvent, 鼠标单击事件 etc.

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

如果您想掌握引发 CanExecute 的控制权,您可以使用委托命令 http://msdn.microsoft.com/en-us/library/gg431410%28v=pandp.40%29.aspx由棱镜提供。CanExecute仅当您显式调用时才会调用委托RaiseCanExecuteChanged()委托命令公开的方法。

合并评论来回答

自从切换到 VS 后,每次都会遇到断点 CommandManager RequerySuggested 事件在失去焦点时被调用 窗口和窗口的激活属性发生变化。这就是为什么你 请注意,当您移动到 VS 因为焦点从 WPF 窗口移动到 Visual Studio。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

更新的标题:为什么 ICommand.CanExecute 一直被调用,而不是像事件一样工作? 的相关文章

  • 从空白启动时 VSTO 功能区不显示解决方案

    如果我从 文件 新建项目 菜单创建一个新的 Excel 2013 和 2016 VSTO 加载项 项目 然后单击 项目 添加新项目 gt 功能区 可视化设计器 则一切正常 我启动了应用程序 我的功能区显示在 Excel 中 但是 如果我首先
  • 打印对话框不显示在 64 位计算机上的 Crystal Report Viewer 中

    我有一个运行 Windows 2008 Server 64 位的客户端 他正在运行我们的软件 它具有内置的水晶报表查看器功能 无论如何 打印对话都行不通 它在我们的 32 位机器上运行并且我们验证了它 我在我们的 64 位机器上验证了它 打
  • 具有自定义镶边的 WPF 窗口在右侧和底部有不需要的轮廓

    我使用 Microsoft Windows Shell dll 创建了带有自定义镶边的 WPF 窗口 这是代码
  • 在 WPF 树视图中获取 FullPath?

    如果我以编程方式创建 WPF TreeView 例如 TreeView treeView lt added in the designer TreeViewItem rootNode new TreeViewItem rootNode He
  • 如何创建自动滚动文本框

    我有一个 WPF 应用程序 其中包含一个多行文本框 用于显示调试文本输出 如何设置文本框 以便将文本附加到框中时 它会自动滚动到文本框的底部 我正在使用 MVVM 模式 理想情况下 纯 XAML 方法会很好 TextBox 本身不一定是焦点
  • WPF:当 FontStyle 为 Oblique 时,剪切文本块中最后一个字母的部分

    我有一个简单的 XAML 示例
  • 在 MVVM 中设置可见性的最佳方法

    In my View我有三个对象 其中一个在任何给定时间都是可见的 在我的Model我有一个枚举来代表这三个状态 我应该如何实施我的ViewModel a 为每个对象的可见性创建一个布尔值 并将每个对象绑定到该布尔值 使用 bool gt
  • App 对象中的 Log4Net?

    我正在开始在 WPF 桌面应用程序中进行日志记录 使用 Log4Net 作为日志记录组件 这是我的问题 在一个简单的桌面应用程序中 是否有任何理由不将我的记录器实例化为 App 类 App xaml cs 的属性 就像这样 public p
  • 将字符串转换为双精度 - VB

    VB中有没有一种有效的方法来检查字符串是否可以转换为双精度型 我目前正在尝试将字符串转换为双精度型 然后查看它是否引发异常 但这似乎减慢了我的申请速度 Try if number then format it current CDbl x
  • Android中如何通过ViewModel类在Activity和Fragment之间共享数据?

    我想知道是否可以传递一个在 Activity 类中声明的字符串数据 并将该字符串数据传递给 ViewModel 类 然后将数据传递给 Fragment 类 视图模型类 class TimeTableViewModel extends Vie
  • DataGridView 使用 Structure 和 LINQ 来排序 txt 文件

    当我的程序出现问题时 我能够将所有数据拉入网格并进入正确的列 行 但是 我相信我的 LINQ 查询是错误的 它没有使第三列正确划分并插入正确的数据 我的结果 https gyazo com 0f307a10dff4c015a361708ec
  • Relay/ICommand 与 DelegateCommand——差异

    据我所知 下面的代码可以从 Relay ICommand 命令更改为 Delegate 命令 并且仍然以相同的方式绑定命令 如果我错了 它们的区别和用途是什么 private DelegateCommand something public
  • 如何在标准 WPF ListView 中启用 UI 虚拟化

    我正在使用 NET 4 5 VS2012 并且我有一个 ListView 看起来像这样
  • 了解使用 Windows 本机 WPF 客户端进行 ADFS 登录

    我已经阅读了大量有关 ADFS 与 NodeJS Angular 或其他前端 Web 框架集成以及一般流程如何工作的文献 并通过 Auth0 Angular 起始代码构建了概念证明 但我不明白如何这可以与本机 WPF Windows 应用程
  • 如何使用 WPF 从 XML 文件创建树视图?

    这是 XML 文件
  • 将多个实时视频流拉入 WPF

    我想创建一个应用程序 将由同轴电缆 hdmi 或其他标准提供的多个实时视频源拉入 WPF 中进行操作 即应用一些转换或像素着色器 然后将其输出到监视器 开始使用这个应用程序时我会考虑什么 有没有任何硬件可以让事情变得更容易 如果您通过同轴电
  • 不支持 URI 前缀

    我正在尝试使用以下方法加载和播放波形文件 SoundPlayer simpleSound new SoundPlayer pack application MyAssembly component Sounds 10meters wav s
  • WPF 中处理系统关闭

    如何在 WPF 中重写 WndProc 当我的窗口关闭时 我尝试检查我正在使用的文件是否被修改 如果是 我必须提示用户 你想保存更改吗 消息 然后关闭正在使用的文件和窗口 但是 当我的窗口仍然打开时 我无法处理用户重新启动 关闭 注销的情况
  • 获取 TreeView 中子节点的 SelectedIndex

    我目前正在使用 C 开发一个 wpf 项目 我创建了一个树视图 其中包含父节点和子节点 我想知道是否有办法获取用户单击的子节点的索引 类似于使用组合框时的 SelectedIndex 我尝试过各种方法 例如 int val TreeView
  • 如何使用 VB.NET 打开受密码保护的共享网络文件夹?

    我需要在网络上打开受密码保护的共享文件夹才能访问 Access 97 数据库 如何打开文件夹并输入密码 在这里找到http www mredkj com vbnet vbnetmapdrive html http www mredkj co

随机推荐