RelayCommand.CanExecute不在UI中更新IsEnabled

时间:2013-03-27 08:50:31

标签: button windows-phone mvvm-light relaycommand

我有一个Windows Phone 8应用程序,我有一个名为RelayCommand的{​​{1}}实例。我有一个DiscoverExpansionModulesCommand属性绑定到Command的按钮。首次加载应用时,会正确启用或禁用该按钮。但是,当在页面上并且我想要更改命令是否可以执行时,方法DiscoverExpansionModulesCommand会正确触发并返回正确的true或false值,但按钮不会反映它。为什么按钮没有更新它的UI?我在http://social.msdn.microsoft.com/Forums/en-US/silverlightarchieve/thread/48a341e4-f512-4c33-befd-b614404b4920/

找到了关于此问题的另一篇文章

我的ViewModel:

CanExecuteDiscoverExpansionModulesCommand()

和XAML

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using MAL.Portable.Commands;
using MAL.Portable.Message;
using MAL.Portable.Model;
using System;
using System.Collections.Generic;
using System.Windows.Input;

namespace MAL.Portable.ViewModel
{
    public class SettingsViewModel : ViewModelBase
    {
        // Define an observable collection property that controls can bind to.
        private List<Setting> settings;
        private String controllerUrl;
        private String controllerPort;
        private String temperature;
        private Wifi wifi;
        private Boolean connected;
        private Boolean checkingConnection;


        public SettingsViewModel()
        {
            DiscoverExpansionModulesCommand = new RelayCommand(OnDiscoverExpansionModules, CanExecuteDiscoverExpansionModulesCommand);

            Messenger.Default.Register<RetrieveSettingsMessage>
            (
                 this, (action) => RetrievedListsMessage(action)
            );

            Messenger.Default.Send<GetSettingsMessage>(new GetSettingsMessage());
        }

        public ICommand DiscoverExpansionModulesCommand
        {
            get;
            private set;
        }

        public String ConnectionStatus
        {
            get
            {
                if (checkingConnection) 
                    return "checking";
                else
                    return connected ? "connected" : "not connnected";
            }
        }

        private Boolean CanExecuteDiscoverExpansionModulesCommand()
        {
            return connected;
        }

        private void OnDiscoverExpansionModules()
        {

        }

        private void CheckConnection()
        {
            wifi = null;
            if (!String.IsNullOrWhiteSpace(ControllerUrl) && !String.IsNullOrWhiteSpace(ControllerPort) && !checkingConnection)
            {
                checkingConnection = true;
                wifi = new ReefAngelWifi(controllerUrl, controllerPort);
                wifi.TestConnectionComplete += wifi_TestConnectionComplete;
                wifi.RequestFail += wifi_RequestFail;
                wifi.BeginTestConnection();
            }
        }

        private void wifi_RequestFail(object sender, RequestExceptionEventArgs e)
        {
            connected = false;
            checkingConnection = false;
            RaisePropertyChanged("ConnectionStatus");
        }

        private void wifi_TestConnectionComplete(object sender, TestConnectionEventArgs e)
        {
            connected = e.TestSuccessful;
            checkingConnection = false;
            DiscoverExpansionModulesCommand.CanExecute(null);
            RaisePropertyChanged("ConnectionStatus");
            RaisePropertyChanged("DiscoverExpansionModulesCommand");
        }

        private object RetrievedListsMessage(RetrieveSettingsMessage action)
        {
            settings = action.Settings;
            CheckConnection();
            return null;
        }

        private String GetStringValue(String key)
        {
            if (settings == null) return String.Empty;
            var item = settings.Find(x => x.Key == key);
            if (item == null) return String.Empty;
            else return item.Value;
        }

        private Boolean GetBooleanValue(String key)
        {
            if (settings == null) return false;
            var item = settings.Find(x => x.Key == key);
            if (item == null) return false;
            else return Boolean.Parse(item.Value);
        }
    }
}

我正在使用MVVM Light可移植类库。

2 个答案:

答案 0 :(得分:5)

当您在RelayCommand.RaiseCanExecuteChanged()方法中评估的条件发生变化时,您需要致电CanExecute

修改

    private void wifi_RequestFail(object sender, RequestExceptionEventArgs e)
    {
        connected = false;
        checkingConnection = false;
        RaisePropertyChanged("ConnectionStatus");
        DiscoverExpansionModulesCommand.RaiseCanExecuteChanged();
    }

    private void wifi_TestConnectionComplete(object sender, TestConnectionEventArgs e)
    {
        connected = e.TestSuccessful;
        checkingConnection = false;
        DiscoverExpansionModulesCommand.CanExecute(null);
        RaisePropertyChanged("ConnectionStatus");
        RaisePropertyChanged("DiscoverExpansionModulesCommand");
        DiscoverExpansionModulesCommand.RaiseCanExecuteChanged();
    }

这不会导致循环,因为它只告诉RelayCommand重新执行指定的CanExecute方法。在您的情况下,这仅表示已读取属性CanExecuteDiscoverExpansionModulesCommand

答案 1 :(得分:1)

这似乎是一个跨线程问题。弄清楚如何在PCL中调用Dispatcher很棘手,但我在此处找到了它:Update UI thread from portable class library