MattP
Well-known member
Posting this in the Silverlight forum since that's what I'm using and I don't see an MVVM section. If a mod needs to move it to the MVC section since it's a pattern question please do so.
I'm having an issue getting a button to be disabled when CanExecute in my ViewModel is set to false.
Here's the code for my button:
Nothing happens when you click on the button because CanExecute is false but the button is still clickable rather than disabled.
Here's the code for my DelegateCommand class:
Here are the entities I'm working with in the ViewModel:
Initialization code for my DelegateCommand:
From everything I've read this should handle the IsEnabled property on the button.
To get around this I've created a new property which I'm raising whenever SelectedCollateral is set and then manually bound it to the IsEnabled property on the button.
This seems hacky to me and shouldn't be necessary from what I've read about MVVM.
If anyone could point out my error it would be appreciated. Thanks in advance.
I'm having an issue getting a button to be disabled when CanExecute in my ViewModel is set to false.
Here's the code for my button:
VB.NET:
<Button Content="Remove Collateral" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Source={StaticResource vm}, Path=DeleteCollateralCommand}"
CommandParameter="{Binding DataContext, ElementName=dataGrid}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Nothing happens when you click on the button because CanExecute is false but the button is still clickable rather than disabled.
Here's the code for my DelegateCommand class:
VB.NET:
Public Class DelegateCommand
Implements ICommand
Dim _executeAction As Action(Of Object)
Dim _canExecuteCache As Boolean
Dim _canExecute As Func(Of Object, Boolean)
''' <summary>
''' Initializes a new instance of the <see cref="DelegateCommand"/> class.
''' </summary>
''' <param name="executeAction">The execute action.</param>
''' <param name="canExecute">Whether it can execute.</param>
Public Sub New(ByVal executeAction As Action(Of Object), ByVal canExecute As Func(Of Object, Boolean))
_executeAction = executeAction
_canExecute = canExecute
End Sub
''' <summary>
''' Determines whether the command can execute in its current state.
''' </summary>
''' <param name="parameter">Data used by the command.</param>
''' <returns>True if the command can be executed.</returns>
Public Function CanExecute(ByVal parameter As Object) As Boolean _
Implements ICommand.CanExecute
Dim temp = _canExecute(parameter)
If _canExecuteCache <> temp Then
_canExecuteCache = temp
RaiseEvent CanExecuteChanged(Me, New EventArgs)
End If
Return _canExecuteCache
End Function
''' <summary>
''' Occurs when changes happen that affects whether the command should execute.
''' </summary>
Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) _
Implements ICommand.CanExecuteChanged
''' <summary>
''' Defines method to call when the command is invoked.
''' </summary>
''' <param name="parameter">Data used by the command.</param>
Public Sub Execute(ByVal parameter As Object) _
Implements ICommand.Execute
_executeAction(parameter)
End Sub
End Class
Here are the entities I'm working with in the ViewModel:
VB.NET:
Public ReadOnly Property Collateral As EntitySet(Of Collateral)
Get
Return ctx.Collaterals
End Get
End Property
Private _selectedCollateral As Collateral
Public Property SelectedCollateral As Collateral
Get
Return _selectedCollateral
End Get
Set(ByVal value As Collateral)
_selectedCollateral = value
RaisePropertyChanged("SelectedCollateral")
End Set
End Property
Initialization code for my DelegateCommand:
VB.NET:
CollateralSelectionChanged = New DelegateCommand(AddressOf OnCollateralSelectionChangedExecute, AddressOf CanChangeCollateralSelection
VB.NET:
Public Property DeleteCollateralCommand As DelegateCommand
Private Sub OnDeleteCollateralExecute(ByVal param As Object)
DirectCast(param, EntitySet(Of Collateral)).Remove(SelectedCollateral)
RaisePropertyChanged("Collateral")
End Sub
Private Function CanDeleteCollateral() As Boolean
Return SelectedCollateral IsNot Nothing
End Function
From everything I've read this should handle the IsEnabled property on the button.
To get around this I've created a new property which I'm raising whenever SelectedCollateral is set and then manually bound it to the IsEnabled property on the button.
VB.NET:
<Button Content="Remove Collateral" IsEnabled="{Binding Source={StaticResource vm}, Path=CanDeleteCollateralProp}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Source={StaticResource vm}, Path=DeleteCollateralCommand}"
CommandParameter="{Binding DataContext, ElementName=dataGrid}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
This seems hacky to me and shouldn't be necessary from what I've read about MVVM.
If anyone could point out my error it would be appreciated. Thanks in advance.