2016-06-10 3 views
2

Я хочу использовать команду делегата PRISM с параметром bool as. Это соответствующий код:DelegateCommand выбрасывает «Указанный прилив недействителен»

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().

Это StackTrace:

>

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 должен быть объектом или обнуляемым, но даже nullable, похоже, не подходит. Как работать с аргументом bool?

Благодаря

ответ

2

Соответствующие свойства параметров команды обычно набраны как объект таким образом любой буквального интерпретируется как строка. Вы должны будете ввести правильный тип, если Prism не сможет автоматически преобразовать ваш тип, но работа с дженериками (например, Nullable<T>) в XAML - это, как правило, боль, поэтому я бы не рекомендовал этого.

Для преобразования простого типа в XAML вы обычно должны быть в состоянии просто использовать привязку, как это: {Binding Source=(sys:Boolean)true}, где sys является отображение XMLNS к System имен в mscorlib конечно.

+0

Я могу жить с этим, и в данный момент это мое обходное решение. Но почему возникает вышеупомянутая проблема? Команда даже не вызывается, вызывается только 'RaiseCanExecuteChanged'. Не следует просто называть 'CanExecuteChangeZoomPan'. Будет ли смысл использовать обобщение, где ограничение? –

+0

'CanExecute' также получает переданный параметр команды, поэтому преобразование также происходит там. Я не думаю, что ограничения могут что-то изменить. –

0

Вы можете просто создать 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!

Смежные вопросы