Click here to Skip to main content
15,896,557 members
Articles / Desktop Programming / WPF

WPF Conditional command

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
7 May 2012CPOL2 min read 11.9K   5  
A view side ICommand that conditionally executes a view-model side ICommand
''' <summary>
'''  ConditionalCommand -- Allows for a command, that is defined by DataContext, to be conditionally executed
''' </summary>
''' <remarks>It inherits <see cref="FrameworkElement" /> to have access to DataContext</remarks>
Friend MustInherit Class ConditionalCommand
    Inherits FrameworkElement
    Implements ICommand

    ''' <summary>
    ''' CanExecute - Rerouted to the command. 
    ''' Returns false if command has not been assigned yet.
    ''' </summary>
    Function CanExecute(parameter As Object) As Boolean Implements System.Windows.Input.ICommand.CanExecute
        Return If(Command Is Nothing, False, Command.CanExecute(CommandParameter))
    End Function

    ''' <summary>
    '''  Execute -- will execute the command depending on 
    '''  the answer from the overridable function <see cref="pShouldCommandExecute"/>
    ''' </summary>
    Sub Execute(parameter As Object) Implements System.Windows.Input.ICommand.Execute
        If pShouldCommandExecute() Then
            Command.Execute(CommandParameter)
            pOnCommandExecuted()
        End If
    End Sub

    ''' <summary>
    '''  pShouldCommandExecute - The command will executed if this returns true
    ''' </summary>
    Protected MustOverride Function pShouldCommandExecute() As Boolean

    ''' <summary>
    '''  pOnCommandExecuted -- called after the command is executed
    ''' </summary>
    Protected MustOverride Sub pOnCommandExecuted()

    ''' <summary>
    '''   CanExecuteChanged -- Handlers for this event will be rerouted to the command's event when it is assigned
    ''' </summary>
    Custom Event CanExecuteChanged As EventHandler Implements System.Windows.Input.ICommand.CanExecuteChanged
        AddHandler(aHandler As EventHandler)
            If Command Is Nothing Then
                pHandlers.Add(aHandler)
            Else
                AddHandler Command.CanExecuteChanged, aHandler
            End If
        End AddHandler
        RemoveHandler(aHandler As EventHandler)
            If Command Is Nothing Then
                pHandlers.Remove(aHandler)
            Else
                RemoveHandler Command.CanExecuteChanged, aHandler
            End If
        End RemoveHandler
        RaiseEvent(sender As Object, e As EventArgs)
        End RaiseEvent
    End Event
    Private pHandlers As New List(Of EventHandler)

    ''' <summary>
    '''  pHandleCommandValueChanged
    ''' </summary>
    ''' <remarks>When the command is finally assigned, handlers for the <see cref="CanExecuteChanged"/> event are rerouted to it. </remarks>
    Private Shared Sub pHandleCommandValueChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
        Dim mCommand = DirectCast(e.NewValue, ICommand)
        If mCommand Is Nothing Then Exit Sub
        Dim mMe = DirectCast(d, ConditionalCommand)
        For Each eHandler In mMe.pHandlers
            AddHandler mCommand.CanExecuteChanged, eHandler
        Next
        mMe.pHandlers.Clear()
    End Sub


    ''' <summary>
    '''  SetAsOwnerOfResources 
    ''' </summary>
    ''' <param name="aOwner">
    ''' The framework element whose DataContent will be inherited by any of its resources that are one of this class </param>
    ''' <remarks></remarks>
    Friend Shared Sub SetAsOwnerOfResources(aOwner As FrameworkElement)
        For Each eResource In aOwner.Resources.Cast(Of DictionaryEntry)()
            If TypeOf eResource.Value Is ConditionalCommand Then
                DirectCast(eResource.Value, ConditionalCommand).Owner = aOwner
            End If
        Next
    End Sub

    ''' <summary>
    '''  The owner of this command. This command will inherit its owner's DataContext
    '''   Must be set externally. See <see cref="SetAsOwnerOfResources" />
    ''' </summary>
    Property Owner As FrameworkElement
        Get
            Return pOwner
        End Get
        Set(value As FrameworkElement)
            pOwner = value
            AddHandler pOwner.DataContextChanged, Sub(sender, e) Me.DataContext = e.NewValue
        End Set
    End Property
    Private pOwner As FrameworkElement

#Region "dependency properties"
    ''' <summary>
    '''   CommandProperty for the command that will be conditionally executed
    ''' </summary>
    Public Shared ReadOnly CommandProperty As DependencyProperty =
                                    DependencyProperty.Register(
                                        name:="Command",
                                        propertyType:=GetType(ICommand),
                                         ownerType:=GetType(ConditionalCommand),
                                         typeMetadata:=New FrameworkPropertyMetadata(
                                                    defaultValue:=Nothing,
                                                    PropertyChangedCallback:=AddressOf pHandleCommandValueChanged))
    ''' <summary>
    '''  Command that will conditionally executed
    ''' </summary>
    Property Command As ICommand
        Get
            Return CType(Me.GetValue(CommandProperty), ICommand)
        End Get
        Set(value As ICommand)
            Me.SetValue(CommandProperty, value)
        End Set
    End Property

    ''' <summary>
    '''   CommandParameterProperty
    ''' </summary>
    Public Shared ReadOnly CommandParameterProperty As DependencyProperty =
                                    DependencyProperty.Register(
                                        name:="CommandParameter",
                                        propertyType:=GetType(Object),
                                         ownerType:=GetType(ConditionalCommand),
                                         typeMetadata:=New FrameworkPropertyMetadata(
                                                    defaultValue:=Nothing))
    ''' <summary>
    '''  CommandParameter
    ''' </summary>
    Overridable Property CommandParameter As Object
        Get
            Return Me.GetValue(CommandParameterProperty)
        End Get
        Set(value As Object)
            Me.SetValue(CommandParameterProperty, value)
        End Set
    End Property
#End Region

End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions