XAML Microsoft社区工具包中继命令无法正常工作

b5lpy0ml  于 2023-02-17  发布在  其他
关注(0)|答案(1)|浏览(114)

我们正在将WPF项目从MVVMLight库迁移到Microsoft CommunityToolkit库。
我们继续遵循共享的Microsoft migration documentation,并相应地更新了所有(大约1200个)命令。
当我们后来得到构建时,我们注意到事件在项目中没有正确触发,命令也不起作用。
但是,SetProperty()方法不运行我的RelayCommands。
下面我们已经解决了这个问题,只有一个命令,我们的用户模型。有超过100+模型和1200ish命令存在。

基本视图模型.cs

public class BaseViewModel : ObservableObject, IDisposable
    {
        protected bool _disposed = false;

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public virtual void Dispose(bool disposing)
        {
            if (_disposed.Equals(false))
            {
                if (disposing)
                {

                }
                _disposed = true;
            }
        }

        private bool _isSaved;
        public bool IsSaved
        {
            get { return _isSaved; }
            set
            {
                SetProperty(ref _isSaved, value, nameof(_isSaved));
            }
        }
    }

登录视图模型

public class LoginViewModel : BaseViewModel
{       
        public LoginViewModel()
        {
            User = new UserModel();
            User.PropertyChanged += User_PropertyChanged; // WHAT WE NEWLY ADDED
            LoginCommand = new RelayCommand<Window>(OnLoginCommandExecuted, CanLoginCommandExecute);
            CancelCommand = new RelayCommand<Window>(OnCancelCommandExecuted, CanCancelCommandExecute);
        }

        private void User_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (LoginCommand is not null) LoginCommand.NotifyCanExecuteChanged(); // We should notify it manually..
        }

        private UserModel _user;
        public UserModel User
        {
            get { return _user; }
            set
            {
                SetProperty(ref _user, value, nameof(_user));
            }
        }

        public RelayCommand<Window>? LoginCommand { get; private set; }
        public async void OnLoginCommandExecuted(Window window)
        {       
        //DO STUFF
    }
        public bool CanLoginCommandExecute(Window window)
        {
                //DO STUFF
        }
        
}

登录窗口.xaml

<Window
    x:Class="ProjectName.LoginWindow"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    x:Name="loginWindow">   
    <Button x:Name="btnLogin" Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=loginWindow}" />              
</Window>

有没有办法为活动模型中的所有命令触发NotifyCanExecuteChanged管理器?
在这种情况下我能做什么?下面的实现需要应用于所有的模型和命令吗?这是预期的情况吗?谢谢和快乐的编码。

bq8i3lrv

bq8i3lrv1#

有几件事你可以改变。
在分部类视图模型中,您可以执行以下操作:

[ObservableProperty]
    [AlsoNotifyChangeFor(nameof(FullName))]
    [AlsoNotifyCanExecuteFor(nameof(SaveCommand))]
    private bool _isSaved = true;

    partial void OnIsSavedChanged(bool newValue)
    {
        // Called when IsSaved property changes
    }

IsSaved属性和更改通知的模板代码由代码生成器在分部类中创建。这将降低更改通知中断的风险(就像使用字段而不是属性时所遇到的风险),因为您只需定义私有成员。
您可以添加partial onchanged和onchanging方法,当匹配的属性名称更改或将要更改时,将调用这些方法。
当IsSaved更改时,属性将引发命令的canexecutechanged。
relay命令具有显式notifycanexecutechanged方法
https://learn.microsoft.com/en-us/dotnet/api/microsoft.toolkit.mvvm.input.relaycommand.notifycanexecutechanged?view=win-comm-toolkit-dotnet-7.1
如果没有一个属性适合您,您可以执行以下操作:

CommandManager.InvalidateRequerySuggested()

或者,您可以在视图模型中迭代relay命令,并调用notifycanexecutechanged。
另外请注意,mvvmlight的源代码是可用的。
我在一个.net6项目中使用过它。

相关问题