[英]is operator always results to false in C#
I have this code: 我有以下代码:
public ICommand ChangePageCommand
{
get
{
if (this.changePageCommand == null)
{
this.changePageCommand = new ActionCommand(
parameter => {
this.ChangeViewModel((IPageViewModel)parameter);
},
parameter => parameter is IPageViewModel);
}
return this.changePageCommand;
}
}
Whenever I call this particular command, passing a IPageViewModel
implementing class, the second parameter for ActionCommand
, which is the predicate, always is false. 每当我调用此特定命令时,传递IPageViewModel
实现类,即ActionCommand
的第二个参数(即谓词)始终为false。 I basically have all the IPageViewModel
s in a dictionary. 我基本上在字典中有所有IPageViewModel
。 This is my entire ViewModel class: 这是我的整个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;
}
}
}
For some reason, although the parameter implements the IPageViewModel
, it always results to false. 出于某种原因,尽管参数实现了IPageViewModel
,但它始终会导致结果为false。 Here's my ActionCommand
class: 这是我的ActionCommand
类别:
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);
}
}
}
Here's a use case: 这是一个用例:
<Button Command="{Binding ChangePageCommand}" CommandParameter="{Binding PageViewModels[Dashboard]}">
<TextBlock Style="{StaticResource TitleBarIcon}" Text="" />
</Button>
The thing here is, CanExecute
always evaluates to false, hence, the Button click is disable here. 这里的事情是, CanExecute
总是计算为false,因此在此禁用了Button单击。 But, I tried replacing the predicate to just true
which makes the program work totally as expected. 但是,我尝试将谓词替换为true
,这使程序完全可以按预期运行。 Here's the DashboardViewModel which is what I'm passing to the command here: 这是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();
}
}
}
}
As the parameter
is the same to both CanExecute
and Execute
, the only way for your snippet 由于CanExecute
和Execute
的parameter
相同,因此代码段的唯一方法
this.changePageCommand = new ActionCommand(
parameter => { this.ChangeViewModel((IPageViewModel)parameter); },
parameter => parameter is IPageViewModel);
to not throw an exception in the first assignment (explicit casting) and to yield null as result in the second assignment is, to pass null
as parameter. 在第一个赋值中不抛出异常(显式强制转换),并在第二个赋值中产生null作为结果,将null
作为参数传递。 So check for null and react appropriatly. 因此,请检查是否为空并做出适当的反应。
Hope this helps. 希望这可以帮助。
Change the xaml of the button the otherway around so the CommandParameter is evaluated before the command. 否则,请更改按钮的xaml,以便在执行命令之前先评估CommandParameter。
<Button CommandParameter="{Binding PageViewModels[Dashboard]}" Command="{Binding ChangePageCommand}">
<TextBlock Style="{StaticResource TitleBarIcon}" Text="" />
</Button>
Also when you change the CommandParameter's binding, you need to manually force the command's CanExecuteChanged evaluation. 同样,在更改CommandParameter的绑定时,还需要手动强制执行命令的CanExecuteChanged评估。
You are probably better off using just the name as the parameter however. 但是,最好只使用名称作为参数。
<Button Command="{Binding ChangePageCommand}" CommandParameter="Dashboard">
<TextBlock Style="{StaticResource TitleBarIcon}" Text="" />
</Button>
And in the viewmodel make following changes. 并在视图模型中进行以下更改。
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.