WPF 解決 CommandParameter 引數不更新問題

夏秋初發表於2024-03-09

參考

  • https://devbox.cn/p/WPFCommandParame_71b81418.html

環境

軟體/系統 版本 說明
Windows Windows 10 專業版 22H2 19045.4046
Microsoft Visual Studio Microsoft Visual Studio Community 2022 (64 位) - 17.6.5
Microsoft .Net SDK 8.0.101 手動安裝
Microsoft .Net SDK 7.0.306 Microsoft Visual Studio 攜帶
.net 6.x 建立當前文章演示 WPF 專案時指定 .net 版本所選擇的框架
Prism Template Pack 2.4.1 Microsoft Visual Studio 擴充套件
XAML Style for Visual Studio 2022 3.2311.2 Microsoft Visual Studio 擴充套件(XAML 自動格式化)
HandyControl 3.5.1 NuGet包
Prism.DryIoc 8.1.97 NuGet包

提示

本文使用到了 Prism ,但是未使用該框架也可以用本方法解決。

正文

問題

在 ViewModel 中定義了 bool Listening ,在 XAML CommandParameter 中進行繫結,當 Listening 值更新時,CommandParameter 接收的 Listening 不更新。

解決

  1. 當使用 Prism 框架時,視窗的 MVVM 需要繼承 BindableBase,並且引數更新時呼叫 SetProperty 方法(通知 UI 引數進行了更新)。
// 以 MainWindow 視窗與 Listening 引數舉例
using FileMonitoring.Commands;
using FileMonitoring.Views;
using Prism.Mvvm;
using System.ComponentModel;
using System.Data.Common;
using System.Windows;
using System.Windows.Input;
using System.Xml.Linq;
namespace FileMonitoring.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private bool _listening = false;

        public bool Listening
        {
            get { return _listening; }
            set { 
                SetProperty(ref _listening, value);
            }
        }
    }
}
  1. 命令介面繼承 ICommand 時實現了 public event EventHandler CanExecuteChanged;,需要調整為如下程式碼才可以重新觸發 CanExecute 事件 :
			public event EventHandler CanExecuteChanged {
				add{CommandManager.RequerySuggested += value;}
				remove{CommandManager.RequerySuggested -= value;}
			}

完整命令介面 ICommand 實現為:

	using System;
	using System.Collections.Generic;
	using System.Diagnostics;
	using System.Linq;
	using System.Text;
	using System.Threading.Tasks;
	using System.Windows;
	using System.Windows.Input;
	using static ImTools.ImMap;

	namespace FileMonitoring.Commands
	{
		/**
		 * 開啟監聽命令
		 */
		internal class OnStartListenCommand : ICommand
		{

			private Action<object?> _execute;

			public OnStartListenCommand(Action<object?> execute)
			{
				_execute = execute;
			}

			public event EventHandler CanExecuteChanged {
				add{CommandManager.RequerySuggested += value;}
				remove{CommandManager.RequerySuggested -= value;}
			}

			public bool CanExecute(object parameter)
			{
				return !(parameter as bool?) ?? false;
			}

			public void Execute(object parameter)
			{
				Trace.WriteLine("開啟監聽命令");
				_execute(parameter);
			}
		}
	}

相關文章