代码之家  ›  专栏  ›  技术社区  ›  codez

在C中,is运算符总是导致false#

  •  0
  • codez  · 技术社区  · 9 年前

    我有这个代码:

        public ICommand ChangePageCommand
        {
            get
            {
                if (this.changePageCommand == null)
                {
                    this.changePageCommand = new ActionCommand(
                        parameter => {
                                this.ChangeViewModel((IPageViewModel)parameter);
                            },
                        parameter => parameter is IPageViewModel);
                }
    
                return this.changePageCommand;
            }
        }
    

    每当我调用这个特定命令时 IPageViewModel 实现类,第二个参数 ActionCommand 在字典里。这是我的整个ViewModel类:

    using VexLibrary.Windows;
    using System.Windows.Input;
    using System.Collections.Generic;
    using VexLibrary.DesktopClient.ViewModels;
    using System.Linq;
    
    namespace VexLibrary.DesktopClient.ViewModels
    {
        class ApplicationViewModel : ViewModel
        {
            private ICommand changePageCommand;
            private IPageViewModel currentPageViewModel;
            private Dictionary<string, IPageViewModel> pageViewModels;
    
            public ApplicationViewModel()
            {
                this.PageViewModels.Add("Dashboard", new DashboardViewModel(this));
                this.PageViewModels.Add("Statistics", new StatisticsViewModel());
    
                this.CurrentPageViewModel = this.PageViewModels["Dashboard"];
            }
    
            public ICommand ChangePageCommand
            {
                get
                {
                    if (this.changePageCommand == null)
                    {
                        this.changePageCommand = new ActionCommand(
                            parameter => {
                                    this.ChangeViewModel((IPageViewModel)parameter);
                                },
                            parameter => parameter is IPageViewModel);
                    }
    
                    return this.changePageCommand;
                }
            }
    
    
    
            public IPageViewModel CurrentPageViewModel
            {
                get
                {
                    return this.currentPageViewModel;
                }
                set
                {
                    if (this.currentPageViewModel != value)
                    {
                        this.currentPageViewModel = value;
                        NotifyPropertyChanged();
                    }
                }
            }
    
            public Dictionary<string, IPageViewModel> PageViewModels
            {
                get
                {
                    if (this.pageViewModels == null)
                        this.pageViewModels = new Dictionary<string, IPageViewModel>();
    
                    return this.pageViewModels;
                }
            }
    
    
            public void ChangeViewModel(IPageViewModel viewModel)
            {
                this.CurrentPageViewModel = this.pageViewModels.FirstOrDefault(element => element.Value == viewModel).Value;
            }
        }
    }
    

    出于某种原因,尽管参数实现了 IPageViewModel ,它总是导致错误。这是我的 行动命令 类别:

    using System;
    using System.Windows.Input;
    
    namespace VexLibrary.Windows
    {
        public sealed class ActionCommand : ICommand
        {
            private readonly Action<Object> action;
            private readonly Predicate<Object> predicate;
            public event EventHandler CanExecuteChanged;
    
            /// <summary>
            /// Initializes a new instance of the <see cref="ActionCommand"/> class.
            /// </summary>
            /// <param name="action">The <see cref="Action"/> delegate to wrap.</param>
            public ActionCommand(Action<Object> action) : this(action, null)
            {
            }
    
            /// <summary>
            /// Initializes a new instance of the <see cref="ActionCommand"/> class.
            /// </summary>
            /// <param name="action">The <see cref="Action"/> delegate to wrap.</param>
            /// <param name="predicate">The <see cref="Predicate{Object}"/> that determines whether the action delegate may be invoked.</param>
            public ActionCommand(Action<Object> action, Predicate<Object> predicate)
            {
                if (action == null)
                {
                    throw new ArgumentNullException("action", "You must specify an Action<T>.");
                }
    
                this.action = action;
                this.predicate = predicate;
            }
    
            /// <summary>
            /// Defines the method that determines whether the command can execute in its current state.
            /// </summary>
            /// <returns>
            /// true if this command can be executed; otherwise, false.
            /// </returns>
            /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
            public bool CanExecute(object parameter)
            {
                if (predicate == null)
                {
                    return true;
                }
                return predicate(parameter);
            }
    
            /// <summary>
            /// Defines the method to be called when the command is invoked.
            /// </summary>
            /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
            public void Execute(object parameter)
            {
                action(parameter);
            }
    
            /// <summary>
            /// Executes the action delegate without any parameters.
            /// </summary>
            public void Execute()
            {
                Execute(null);
            }
        }
    }
    

    下面是一个用例:

                            <Button Command="{Binding ChangePageCommand}"  CommandParameter="{Binding PageViewModels[Dashboard]}">
                                <TextBlock Style="{StaticResource TitleBarIcon}" Text="&#xE10F;" />
                            </Button>
    

    这里的问题是, CanExecute 始终计算为false,因此,此处的按钮单击是禁用的。但是,我尝试将谓词替换为 true 这使得程序完全按照预期工作。这里是DashboardViewModel,这是我在这里传递给命令的:

    using VexLibrary.Windows;
    using System.Windows.Input;
    
    namespace VexLibrary.DesktopClient.ViewModels
    {
        class DashboardViewModel : ViewModel, IPageViewModel
        {
            private string name = "Dashboard";
            private ApplicationViewModel parentViewModel;
            private ICommand statisticsPageCommand;
    
            public DashboardViewModel(ApplicationViewModel parentViewModel)
            {
                this.parentViewModel = parentViewModel;
            }
    
            public ICommand StatisticsPageCommand
            {
                get
                {
                    return new ActionCommand(
                        parameter => this.parentViewModel.ChangeViewModel(this.parentViewModel.PageViewModels["Statistics"])
                    );
                }
            }
    
            public string Name
            {
                get
                {
                    return this.name;
                }
                set
                {
                    this.name = value;
                    NotifyPropertyChanged();
                }
            }
        }
    }
    
    2 回复  |  直到 9 年前
        1
  •  2
  •   Jürgen Röhr    9 年前

    作为 parameter 两者都一样 CanExecute Execute ,您的代码片段的唯一方法

    this.changePageCommand = new ActionCommand(
      parameter => { this.ChangeViewModel((IPageViewModel)parameter); },
      parameter => parameter is IPageViewModel);
    

    null 作为参数。因此,检查空值并适当地作出反应。

    希望这有帮助。

        2
  •  1
  •   Janne Matikainen    9 年前

    反过来更改按钮的xaml,以便在命令之前评估命令参数。

    <Button CommandParameter="{Binding PageViewModels[Dashboard]}" Command="{Binding ChangePageCommand}">
        <TextBlock Style="{StaticResource TitleBarIcon}" Text="&#xE10F;" />
    </Button>
    

    此外,更改命令参数的绑定时,需要手动强制命令的CanExecuteChanged求值。

    不过,您最好只使用名称作为参数。

    <Button Command="{Binding ChangePageCommand}" CommandParameter="Dashboard">
        <TextBlock Style="{StaticResource TitleBarIcon}" Text="&#xE10F;" />
    </Button>
    

    并在viewmodel中进行以下更改。

    public ICommand ChangePageCommand
    {
        get
        {
            return new Command(
                    parameter => { this.ChangeViewModel(parameter as string); },
                    parameter =>
                        {
                            var str = parameter as string;
                            return !string.IsNullOrEmpty(str) && this.PageViewModels.ContainsKey(str);
                        });
        }
    }
    
    public void ChangeViewModel(string viewName)
    {
        this.CurrentPageViewModel = this.pageViewModels.FirstOrDefault(element => element.Key == viewName).Value;
    }