DelegateCommand 抛出 "Specified cast is not valid"
DelegateCommand throws "Specified cast is not valid"
我想使用带有布尔值作为参数的 PRISM 委托命令。这是相关代码:
public class ChartViewModel : BindableBase
{
public DelegateCommand<bool?> ChangeZoomPanCommand { get; private set; }
private bool isInRealtimeMode;
public bool IsInRealtimeMode
{
get { return isInRealtimeMode; }
set
{
SetProperty(ref isInRealtimeMode, value);
ChangeZoomPanCommand.RaiseCanExecuteChanged();
}
}
private bool dragToZoom;
public bool DragToZoom
{
get { return dragToZoom; }
set { SetProperty(ref dragToZoom, value); }
}
public ChartViewModel()
{
ChangeZoomPanCommand = new DelegateCommand<bool?>(ExecuteChangeZoomPan, CanExecuteChangeZoomPan);
IsInRealtimeMode = true;
DragToZoom = true;
}
private bool CanExecuteChangeZoomPan(bool? arg)
{
return !IsInRealtimeMode;
}
private void ExecuteChangeZoomPan(bool? enableZoom)
{
if (enableZoom.HasValue)
{
DragToZoom = enableZoom.Value;
}
}
}
当我在 CanExecuteChangeZoomPan
中设置断点时,它永远不会被击中。问题发生在 ChangeZoomPanCommand.RaiseCanExecuteChanged()
.
之后
这是堆栈跟踪:
>
at Prism.Commands.DelegateCommand`1.<>c__DisplayClass1_0.<.ctor>b__1(Object o)
at Prism.Commands.DelegateCommandBase.CanExecute(Object parameter)
at Prism.Commands.DelegateCommandBase.System.Windows.Input.ICommand.CanExecute(Object parameter)
at MS.Internal.Commands.CommandHelpers.CanExecuteCommandSource(ICommandSource commandSource)
at System.Windows.Controls.Primitives.ButtonBase.UpdateCanExecute()
at System.Windows.Controls.Primitives.ButtonBase.HookCommand(ICommand command)
at System.Windows.Controls.Primitives.ButtonBase.OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue)
at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange)
at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
at System.Windows.Data.BindingExpression.Activate(Object item)
at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
at System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance)
at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance)
at MS.Internal.Data.DataBindEngine.Run(Object arg)
at MS.Internal.Data.DataBindEngine.OnLayoutUpdated(Object sender, EventArgs e)
at System.Windows.ContextLayoutManager.fireLayoutUpdateEvent()
at System.Windows.ContextLayoutManager.UpdateLayout()
at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
at System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
at System.Windows.Media.MediaContext.AnimatedRenderMessageHandler(Object resizedCompositionTarget)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
如果我将参数类型更改为字符串,一切似乎都有效。然后我当然得到一个 "False" 字符串作为参数,因为那是我的 xaml 命令参数。为什么这不适用于任何 T,因为 T 似乎没有限制。我发现 T 必须是对象或可为空的困难方法,但即使可为空似乎也不合适。如何使用 bool 参数?
谢谢
相关的命令参数属性通常被键入为对象,因此任何文字都被解释为字符串。如果 Prism 无法自动转换为您的类型,您将必须传递正确的类型,但在 XAML 中使用泛型(如 Nullable<T>
)通常很痛苦,因此我不建议这样做.
要转换为 XAML 中的简单类型,您通常应该能够使用这样的绑定:{Binding Source=(sys:Boolean)true}
,其中 sys
是到 System
命名空间当然在 mscorlib
中。
您可以只创建一个 DelegateCommand<object>
而不是 DelegateCommand<bool?>
,然后像这样处理它:
void ExecuteChangeZoomPan(object obj)
{
if (obj is bool?)
{
bool? arg = obj as bool?;
// The rest of the code goes here.
}
}
这样,ExecuteChangeZoomPan
可以很灵活,接受像System.DateTime
一样复杂的类型!
这就是我创建 DelegateCommand 的新实例的方式
ICommand ConnectCommand = new DelegateCommand<object>(ConnectExecute,ConnectCanExecute);
然后如果你想提高零钱
((DelegateCommand<object>)ConnectCommand).RaiseCanExecuteChanged();
我想使用带有布尔值作为参数的 PRISM 委托命令。这是相关代码:
public class ChartViewModel : BindableBase
{
public DelegateCommand<bool?> ChangeZoomPanCommand { get; private set; }
private bool isInRealtimeMode;
public bool IsInRealtimeMode
{
get { return isInRealtimeMode; }
set
{
SetProperty(ref isInRealtimeMode, value);
ChangeZoomPanCommand.RaiseCanExecuteChanged();
}
}
private bool dragToZoom;
public bool DragToZoom
{
get { return dragToZoom; }
set { SetProperty(ref dragToZoom, value); }
}
public ChartViewModel()
{
ChangeZoomPanCommand = new DelegateCommand<bool?>(ExecuteChangeZoomPan, CanExecuteChangeZoomPan);
IsInRealtimeMode = true;
DragToZoom = true;
}
private bool CanExecuteChangeZoomPan(bool? arg)
{
return !IsInRealtimeMode;
}
private void ExecuteChangeZoomPan(bool? enableZoom)
{
if (enableZoom.HasValue)
{
DragToZoom = enableZoom.Value;
}
}
}
当我在 CanExecuteChangeZoomPan
中设置断点时,它永远不会被击中。问题发生在 ChangeZoomPanCommand.RaiseCanExecuteChanged()
.
这是堆栈跟踪:
>
at Prism.Commands.DelegateCommand`1.<>c__DisplayClass1_0.<.ctor>b__1(Object o)
at Prism.Commands.DelegateCommandBase.CanExecute(Object parameter)
at Prism.Commands.DelegateCommandBase.System.Windows.Input.ICommand.CanExecute(Object parameter)
at MS.Internal.Commands.CommandHelpers.CanExecuteCommandSource(ICommandSource commandSource)
at System.Windows.Controls.Primitives.ButtonBase.UpdateCanExecute()
at System.Windows.Controls.Primitives.ButtonBase.HookCommand(ICommand command)
at System.Windows.Controls.Primitives.ButtonBase.OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue)
at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange)
at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange)
at System.Windows.Data.BindingExpression.Activate(Object item)
at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
at System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance)
at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance)
at MS.Internal.Data.DataBindEngine.Run(Object arg)
at MS.Internal.Data.DataBindEngine.OnLayoutUpdated(Object sender, EventArgs e)
at System.Windows.ContextLayoutManager.fireLayoutUpdateEvent()
at System.Windows.ContextLayoutManager.UpdateLayout()
at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
at System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
at System.Windows.Media.MediaContext.AnimatedRenderMessageHandler(Object resizedCompositionTarget)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
如果我将参数类型更改为字符串,一切似乎都有效。然后我当然得到一个 "False" 字符串作为参数,因为那是我的 xaml 命令参数。为什么这不适用于任何 T,因为 T 似乎没有限制。我发现 T 必须是对象或可为空的困难方法,但即使可为空似乎也不合适。如何使用 bool 参数?
谢谢
相关的命令参数属性通常被键入为对象,因此任何文字都被解释为字符串。如果 Prism 无法自动转换为您的类型,您将必须传递正确的类型,但在 XAML 中使用泛型(如 Nullable<T>
)通常很痛苦,因此我不建议这样做.
要转换为 XAML 中的简单类型,您通常应该能够使用这样的绑定:{Binding Source=(sys:Boolean)true}
,其中 sys
是到 System
命名空间当然在 mscorlib
中。
您可以只创建一个 DelegateCommand<object>
而不是 DelegateCommand<bool?>
,然后像这样处理它:
void ExecuteChangeZoomPan(object obj)
{
if (obj is bool?)
{
bool? arg = obj as bool?;
// The rest of the code goes here.
}
}
这样,ExecuteChangeZoomPan
可以很灵活,接受像System.DateTime
一样复杂的类型!
这就是我创建 DelegateCommand 的新实例的方式
ICommand ConnectCommand = new DelegateCommand<object>(ConnectExecute,ConnectCanExecute);
然后如果你想提高零钱
((DelegateCommand<object>)ConnectCommand).RaiseCanExecuteChanged();