RelayCommand没有触发CanExecute

时间:2012-02-18 11:03:06

标签: .net silverlight windows-phone-7 mvvm mvvm-light

我正在尝试创建一个绑定到按钮的命令,并依赖于viewmodel的层次结构来表示wp7应用程序中的pivot和pivotitems。它是这样的(我将省略尽可能多的样板代码):

父视图模型:

    public RelayCommand RefreshCommand
    {
        get
        {
            return _refreshCommand;
        }

        set
        {
            if (_refreshCommand == value)
            {
                return;
            }

            var oldValue = _refreshCommand;
            _refreshCommand = value;

            // Update bindings, no broadcast
            RaisePropertyChanged(RefreshCommandPropertyName);
        }
    }


    public RelayCommand<RoutedEventArgs> LoadedCommand
    {
        get
        {
            Action<RoutedEventArgs> getCurrentViewmodel = (args) =>
            {
                CurrentViewModel = SearchByLocationViewModel; // maybe something better...
                RefreshCommand = CurrentViewModel.RefreshResultsCommand;
                RefreshCommand.RaiseCanExecuteChanged();
            };
            return new RelayCommand<RoutedEventArgs>(getCurrentViewmodel);
        }
    }

    public RelayCommand<SelectionChangedEventArgs> PivotItemChangedCommand
    {
        get
        {
            Action<SelectionChangedEventArgs> pivotChanged = (args) =>
            {
                if (args != null)
                {
                    // update current viewmodel
                    CurrentViewModel = ((Microsoft.Phone.Controls.PivotItem) args.AddedItems[0]).DataContext as ISearchViewModelBase;
                    RefreshCommand = CurrentViewModel.RefreshResultsCommand;
                }
            };
            return new RelayCommand<SelectionChangedEventArgs>(pivotChanged);
        }
    }

因此,我在每次加载时都将父视图模型的RefreshCommand属性设置为子命令,并且当选定的pivotitem更改时,我也会这样做。

的Xaml

<Button Command="{Binding RefreshCommand}" />

儿童观看模式

public Func<bool> CanRefresh
{
    get { return () => !IsLoading; }
}

private RelayCommand refreshResultsCommand;

public RelayCommand RefreshResultsCommand
{
    get
    {
        Action doRefresh = () =>
        {
            SearchResults.Clear();
            this._pageNumber = 0;
            AddItems();
        };
        return refreshResultsCommand = refreshResultsCommand ?? new RelayCommand(doRefresh, CanRefresh);
    }
}

会发生什么,CanRefresh永远不会被调用。命令工作正常,具体取决于它调用一个AddItems(这是在每个子视图模型中实现不同的虚方法)或另一个,但它就像CanExecute永远不会被引发一样。我正在使用MVVM Light工具包。 谢谢!

2 个答案:

答案 0 :(得分:1)

我怀疑永远不会调用CanExecute方法,因为CanExecuteChanged的{​​{1}}事件永远不会在视图层当前绑定的视图模型对象上触发至。由于您在大多数属性访问中创建命令,因此有很多命令,并且您很可能在视图层尚未绑定的命令上触发事件,或者不是更长的时间。

每次调用属性getter时,我都没见过有人创建新命令。您是否可以尝试在构造函数中创建一次命令而不是在每个属性访问上创建命令,并查看是否修复了这些内容?

答案 1 :(得分:0)

每次调用LoadedCommandPivotChangedComman属性时,您都会创建一个新的转发命令。由于SL / WPF经常调用这些属性,因此必须在每次调用属性时都不创建命令。实际上你的RefreshResultsCommand实现了正确的模式。

确保正确实施属性/命令的最佳方法是使用Laurent's MVVM snippets。将它们下载到您的代码段目录并使用它们。除了生产相同的样板代码并因此提高质量外,他们还大大加快了事情的发展!

您也可以use the installer安装这些代码段。