【问题标题】:How to update UI in MVVMLight RelayCommand scenario?如何在 MVVMLight RelayCommand 场景中更新 UI?
【发布时间】:2013-10-04 12:35:45
【问题描述】:

这是一个简单的屏幕,其中一个 textblock 最初是“”,一个 button 称为“设置文本”,它将文本设置为 textblockanother button,称为“清除文本”,它始终清除textblock 中的文本。这就是 XAML 的样子。

<StackPanel>
    <TextBlock Text="{Binding DisplayText, Mode=TwoWay}"></TextBlock>
    <Button Content="Set Text" Command="{Binding SetTextCommand}"></Button>
    <Button Content="Clear Text" Command="{Binding CancelCommand}" 
                                 IsEnabled="{Binding CanCancel, Mode=TwoWay}"/>
</StackPanel>

这是我的 ViewModel 代码。

public class Page1VM : ViewModelBase
    {

        public RelayCommand SetTextCommand { get; private set; }
        public RelayCommand CancelCommand { get; private set; }

        public Page1VM()
        {
            SetTextCommand = new RelayCommand(HandleSetText, CanExecute);
            CancelCommand = new RelayCommand(HandleClearButtonClick, CanExecuteCancel);
        }

        private void HandleSetText(string number)
        {
            DisplayText = number;
        }

        private string _displayText="";
        public string DisplayText
        {
            get { return _displayText; }
            set
            {
                _displayText = value;
                RaisePropertyChanged("DisplayText");
                RaisePropertyChanged("CanCancel");
            }
        }

        private bool _canCancel;
        public bool CanCancel
        {
            get
            {
                if (DisplayText == "")
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            set
            {
                _canCancel = value;
                RaisePropertyChanged("CanCancel");
            }
        }

        private bool CanExecute()
        {
            return true;
        }
        private bool CanExecuteCancel()
        {
            if (DisplayText == "")
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        private void HandleClearButtonClick()
        {
            DisplayText = "";
        }
        private void HandleSetText()
        {
            DisplayText = "Hello";
        }
    }

问题:加载页面时,“清除文本”按钮被禁用,这是预期的并且可以正常工作。

当我单击“设置文本”时,我通过将文本值设置为名为@9​​87654328@ 的属性并将文本设置为文本块,并调用RaisePropertyChanged("CanCancel");,但即使在此之后我的“清除文本”按钮也未启用。背后的原因是什么?我的文本块显示文本值,但“明文”按钮仍未启用。

【问题讨论】:

  • 您是在更改DisplayText 后尝试从命令中删除CanExecuteCancel 还是尝试在CancelCommand 上调用RaiseCanExecuteChanged()?问题是CanCancel,BTW 不需要设置器,因为它是只读的,不会刷新命令的CanExecute

标签: c# windows-phone-7 mvvm windows-phone-8 mvvm-light


【解决方案1】:

据我所知,您的示例中存在一些混淆:您基本上不使用“RelayCommand”的内置“CanExecute”机制,而是在定义@987654321的同时自己重建它@'RealyCommand' 的方法。 'CanExecute' 的想法是自动禁用无法执行命令的控件,因此您无需手动执行。在 'CanExecute' 方法中返回 'true' 并没有真正意义,因为您不一定需要在 RelayCommand 中有 CanExecute 委托(... = new RelayCommand(ExecuteCommand); 很好)。您的方案不起作用,因为您没有在“CancelCommand”上调用“RaisCanExecuteChanged()”。

尝试以下实现,我已删除冗余并插入缺少的“RaiseCanExecuteChanged()”。解释见 cmets:

<StackPanel>
    <TextBlock Text="{Binding DisplayText, Mode=TwoWay}"></TextBlock>
    <Button Content="Set Text" Command="{Binding SetTextCommand}"></Button>
    <Button Content="Clear Text" Command="{Binding CancelCommand}" />
</StackPanel>

并使用这个简化的 ViewModel:

public class Page1VM : ViewModelBase
{
    public RelayCommand SetTextCommand { get; private set; }

    public RelayCommand CancelCommand { get; private set; }

    public Page1VM()
    {
        SetTextCommand = new RelayCommand(ExecuteSetText);

        CancelCommand = new RelayCommand(ExecuteCancel, CanExecuteCancel);
    }

    private string _displayText="";

    public string DisplayText
    {
        get { return _displayText; }
        set
        {
            _displayText = value;
            RaisePropertyChanged("DisplayText");
            RaisePropertyChanged("CanCancel");
            // Raise the CanExecuteChanged event of CancelCommand
            // This makes the UI reevaluate the CanExecuteCancel
            // Set a breakpoint in CanExecuteCancel method to make
            // sure it is hit when changing the text
            CancelCommand.RaiseCanExecuteChanged();                
        }
    }

    private bool CanExecuteCancel()
    {
        // You can simplify the statement like this:
        return DisplayText != "";
    }

    private void ExecuteCancel()
    {
        DisplayText = "";
    }

    private void ExecuteSetText()
    {
        DisplayText = "Hello";
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多