Friday, January 4, 2013

The Connect Class ... that ppl tend to 'Create and Forget'

Here is a class that people usually create to take care of all the database calls.

To use the connect class, you can call it using the following example:

     masterPage.Connect.StartTransaction()
  
     Dim parameters As New List(Of SqlParameter)
  
     parameters.Add(New SqlParameter("@UserName", SqlDbType.VarChar, 75, ParameterDirection.Input, False, 0, 0, String.Empty, DataRowVersion.Current, "Test"))
  
     parameters.Add(New SqlParameter("@Password", SqlDbType.VarChar, 25, ParameterDirection.Input, False, 0, 0, String.Empty, DataRowVersion.Current, 0))
  
     Dim ds = masterPage.Connect.FillDataset("ValidateUser", parameters, True)  

I have added transaction to the class where you can create a transaction and then call all your stored procedures and tell them if you want them to be part of this transaction or not.

 masterPage.Connect.StartTransaction()
  
 masterPage.Connect.EndTransaction()
  
 masterPage.Connect.RollbackTransaction()  

And the Connect class...

 Imports System
  
 Imports System.IO
  
 Imports System.Text
  
 Imports System.Data
  
 Imports System.Data.SqlClient
  
 Namespace Connect
  
   ''' <summary>
  
   ''' <para>Connect class provides connection for various type of external data. Class is not inheritable.</para>
  
   ''' </summary>
  
   Public Class ConnectMe
  
 #Region "Enum"
  
     Public Enum SQLCall
  
       DataSet = 0
  
       DataTable = 1
  
       NonQuery = 2
  
       Reader = 3
  
       Scalar = 4
  
       BulkCopy = 5
  
     End Enum
  
 #End Region
  
 #Region "Constructor"
  
     Public Sub New(ByVal _connString As String)
  
       If Not String.IsNullOrEmpty(_connString) Then Connection = New SqlConnection(_connString)
  
     End Sub
  
     ''' <summary>
  
     ''' Initializes a new instance of the Connect class.
  
     ''' </summary>
  
     Private Sub New()
  
     End Sub
  
 #End Region
  
 #Region "Transaction"
  
     Private transaction As SqlTransaction = Nothing
  
     Public Sub StartTransaction()
  
       Try
  
         If Not Connection Is Nothing AndAlso transaction Is Nothing Then
  
           Connection.Open()
  
           transaction = Connection.BeginTransaction()
  
         End If
  
       Catch ex As Exception
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       End Try
  
     End Sub
  
     Public Sub EndTransaction()
  
       Try
  
         If Not transaction Is Nothing Then transaction.Commit()
  
         If Not transaction Is Nothing Then transaction.Dispose()
  
         If Not Connection Is Nothing AndAlso (Connection.State = ConnectionState.Open) Then Connection.Close()
  
       Catch ex As Exception
  
         MsgBox(ex.ToString)
  
       End Try
  
     End Sub
  
     Public Sub RollbackTransaction()
  
       Try
  
         If Not transaction Is Nothing Then transaction.Rollback()
  
         If Not transaction Is Nothing Then transaction.Dispose()
  
         If Not Connection Is Nothing AndAlso (Connection.State = ConnectionState.Open) Then Connection.Close()
  
       Catch ex As Exception
  
         MsgBox(ex.ToString)
  
       End Try
  
     End Sub
  
 #End Region
  
 #Region "Cleanup"
  
     Public Sub CleanupErrorConnections()
  
       If Not transaction Is Nothing Then transaction.Rollback()
  
       If Not transaction Is Nothing Then transaction.Dispose()
  
       If Not Connection Is Nothing AndAlso (Connection.State = ConnectionState.Open) Then Connection.Close()
  
     End Sub
  
     Public Sub CleanupConnections()
  
       If Not transaction Is Nothing Then transaction.Dispose()
  
       If Not Connection Is Nothing AndAlso (Connection.State = ConnectionState.Open) Then Connection.Close()
  
     End Sub
  
 #End Region
  
 #Region " Public Properties "
  
     ''' <summary>
  
     ''' Gets or sets the string used to open a SQL Server database.
  
     ''' </summary>
  
     ''' <returns>The connection string that includes the source database name, and other parameters needed to establish the initial connection.</returns>
  
     Public Property Connection() As SqlConnection
  
       Get
  
         Return _connection
  
       End Get
  
       Set(ByVal value As SqlConnection)
  
         _connection = value
  
       End Set
  
     End Property
  
     Private _connection As SqlConnection = Nothing
  
 #End Region
  
 #Region " Private Methods "
  
     Private Sub AssignParameters(ByRef cmd As SqlCommand, ByRef cmdParameters As List(Of SqlParameter))
  
       If (cmdParameters Is Nothing) Then Exit Sub
  
       For Each p As SqlParameter In cmdParameters
  
         cmd.Parameters.Add(p)
  
       Next
  
     End Sub
  
 #End Region
  
 #Region "Dataset"
  
     ''' <summary>
  
     ''' Adds or refreshes rows in the System.Data.DataSet to match those in the data source using the System.Data.DataSet name, and creates a System.Data.DataTable named "Table."
  
     ''' DataGridView1.DataSource = sqldb.FillDataset("Select * From dbo.Users", CommandType.Text).Tables(0)
  
     ''' </summary>
  
     ''' <param name="cmd">The Transact-SQL statement or stored procedure to execute at the data source.</param>
  
     ''' <param name="cmdType">A value indicating how the System.Data.SqlClient.SqlCommand.CommandText property is to be interpreted.</param>
  
     ''' <param name="parameters">The parameters of the Transact-SQL statement or stored procedure.</param>
  
     ''' <returns>A System.Data.Dataset object.</returns>
  
     Public Function FillDataSet(ByVal _spName As String, Optional ByVal _parameters As List(Of SqlParameter) = Nothing, Optional ByVal _useTransaction As Boolean = False) As DataSet
  
       Dim sqlda As SqlDataAdapter = Nothing
  
       Dim resultObj As DataSet = Nothing
  
       Try
  
         Using command As New SqlCommand(_spName, Connection)
  
           resultObj = New DataSet
  
           command.CommandType = CommandType.StoredProcedure
  
           ''Assign parameters to command
  
           Me.AssignParameters(command, _parameters)
  
           ''Check if using transaction
  
           If _useTransaction Then command.Transaction = transaction
  
           sqlda = New SqlDataAdapter(command)
  
           sqlda.Fill(resultObj)
  
         End Using
  
       Catch ex As SqlException
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       Catch ex As Exception
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       Finally
  
         If Not _useTransaction Then CleanupConnections()
  
       End Try
  
       Return resultObj
  
     End Function
  
 #End Region
  
 #Region "DataTable"
  
     Public Function FillDataTable(ByVal _spName As String, Optional ByVal _parameters As List(Of SqlParameter) = Nothing, Optional ByVal _useTransaction As Boolean = False) As DataTable
  
       Dim sqlda As SqlDataAdapter = Nothing
  
       Dim resultObj As DataTable = Nothing
  
       Try
  
         Using command As New SqlCommand(_spName, Connection)
  
           resultObj = New DataTable
  
           command.CommandType = CommandType.StoredProcedure
  
           ''Assign parameters to command
  
           Me.AssignParameters(command, _parameters)
  
           ''Check if using transaction
  
           If _useTransaction Then command.Transaction = transaction
  
           sqlda = New SqlDataAdapter(command)
  
           sqlda.Fill(resultObj)
  
         End Using
  
       Catch ex As SqlException
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       Catch ex As Exception
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       Finally
  
         If Not _useTransaction Then CleanupConnections()
  
       End Try
  
       Return resultObj
  
     End Function
  
 #End Region
  
 #Region "NonQuery"
  
     Public Function ExecuteNonQuery(ByVal _spName As String, Optional ByVal _parameters As List(Of SqlParameter) = Nothing, Optional ByVal _useTransaction As Boolean = False) As Integer
  
       Dim resultObj As Integer = Nothing
  
       Try
  
         Using command As New SqlCommand(_spName, Connection)
  
           command.CommandType = CommandType.StoredProcedure
  
           ''Assign parameters to command
  
           Me.AssignParameters(command, _parameters)
  
           ''Check if using transaction
  
           If _useTransaction Then command.Transaction = transaction
  
           resultObj = command.ExecuteNonQuery()
  
         End Using
  
       Catch ex As SqlException
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       Catch ex As Exception
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       Finally
  
         If Not _useTransaction Then CleanupConnections()
  
       End Try
  
       Return resultObj
  
     End Function
  
 #End Region
  
 #Region "Reader"
  
     Public Function ExecuteReader(ByVal _spName As String, Optional ByVal _parameters As List(Of SqlParameter) = Nothing, Optional ByVal _useTransaction As Boolean = False) As IDataReader
  
       Dim resultObj As SqlDataReader = Nothing
  
       Try
  
         Using command As New SqlCommand(_spName, Connection)
  
           command.CommandType = CommandType.StoredProcedure
  
           ''Assign parameters to command
  
           Me.AssignParameters(command, _parameters)
  
           ''Check if using transaction
  
           If _useTransaction Then command.Transaction = transaction
  
           resultObj = command.ExecuteReader(CommandBehavior.CloseConnection)
  
         End Using
  
       Catch ex As SqlException
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       Catch ex As Exception
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       Finally
  
         If Not _useTransaction Then CleanupConnections()
  
       End Try
  
       Return CType(resultObj, IDataReader)
  
     End Function
  
 #End Region
  
 #Region "Scalar"
  
     Public Function ExecuteScalar(ByVal _spName As String, Optional ByVal _parameters As List(Of SqlParameter) = Nothing, Optional ByVal _useTransaction As Boolean = False) As Object
  
       Dim resultObj As Object = Nothing
  
       Try
  
         Using command As New SqlCommand(_spName, Connection)
  
           command.CommandType = CommandType.StoredProcedure
  
           ''Assign parameters to command
  
           Me.AssignParameters(command, _parameters)
  
           ''Check if using transaction
  
           If _useTransaction Then command.Transaction = transaction
  
           resultObj = command.ExecuteScalar()
  
         End Using
  
       Catch ex As SqlException
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       Catch ex As Exception
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       Finally
  
         If Not _useTransaction Then CleanupConnections()
  
       End Try
  
       Return CType(resultObj, IDataReader)
  
     End Function
  
 #End Region
  
 #Region "BulkCopy"
  
     Public Function ExecuteBulkCOpy(ByVal _spName As String, ByVal _desTableName As String, ByVal _sourceTable As DataTable, Optional ByVal _useTransaction As Boolean = False) As Object
  
       Dim resultObj As Object = Nothing
  
       Try
  
         If _useTransaction Then
  
           Using bulkCopy As New SqlBulkCopy(Connection, SqlBulkCopyOptions.Default, transaction)
  
             bulkCopy.DestinationTableName = _desTableName
  
             For Each c As DataColumn In _sourceTable.Columns
  
               Dim map As New SqlBulkCopyColumnMapping(c.ColumnName, c.ColumnName)
  
               bulkCopy.ColumnMappings.Add(map)
  
             Next
  
             bulkCopy.WriteToServer(_sourceTable)
  
           End Using
  
         Else
  
           Using bulkCopy As New SqlBulkCopy(Connection)
  
             bulkCopy.DestinationTableName = _desTableName
  
             For Each c As DataColumn In _sourceTable.Columns
  
               Dim map As New SqlBulkCopyColumnMapping(c.ColumnName, c.ColumnName)
  
               bulkCopy.ColumnMappings.Add(map)
  
             Next
  
             bulkCopy.WriteToServer(_sourceTable)
  
           End Using
  
         End If
  
       Catch ex As SqlException
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       Catch ex As Exception
  
         CleanupErrorConnections()
  
         MsgBox(ex.ToString)
  
       Finally
  
         If Not _useTransaction Then CleanupConnections()
  
       End Try
  
       Return CType(resultObj, IDataReader)
  
     End Function
  
 #End Region
  
   End Class
  
 End Namespace  

Validate all controls in XAML

Ever thought how to validate all controls in WPF when a user submits a form?

With WPF, you have access to the visual tree and with this in hand, I created my little validator called 'BadAssValidation' :) which enumerates down the tree to find controls to validate.

What I do is that on the submit button in my application, I use the 'Command Parameter' and I pass in the Grid where all the controls that I want to validate exists.
 
<Button Height="23" HorizontalAlignment="Right" Margin="0,0,6,26" Name="btSave" VerticalAlignment="Bottom" Width="75" 
Command="{Binding Path=SaveOrderCommand}" CommandParameter="{Binding ElementName=OrderGrid}" Content="Save" />

Note that each individual control needs to have been bound to their own validator in order for the BadAssValidation to check if they have erroros.

<Binding.ValidationRules>
<validate:valMXvarchar300/>
</Binding.ValidationRules>

In the View Model, I now run the BadAssValidation on the Grid. The validator will enumerate through the visual tree to find matching controls. It will then check if any of these controls have failed validation.

'Validate with BadAssValidationDim validationObj As New Validator.BadAssValidation
If Not validationObj.enumVisual(param) Then
...


And here is the BadAssValidator class:

  Public Class BadAssValidation
  
     Private hasErrors As Boolean = False
  
     ''' <summary>
  
     ''' <para>Validation for all textboxes and comboboxes on UserControl.
  
     ''' </para>
  
     ''' <para>This method loops through textboxes and comboboxes on usercontrol
  
     ''' and calls their Binding validation rule if one exists.</para>
  
     ''' </summary>
  
     ''' <param name="visual">Visual</param>
  
     ''' <returns>Boolean: True if all controls pass validation : else false.</returns>
  
     ''' <remarks></remarks>
  
     Public Function enumVisual(ByVal visual As Visual) As Boolean
  
       Try
  
         ''Count children in visual tree node
  
         Dim j As Integer = VisualTreeHelper.GetChildrenCount(visual) - 1
  
         ''Loop through visual child
  
         For i As Integer = 0 To j
  
           Dim childvisual As Visual = CType(VisualTreeHelper.GetChild(visual, i), Visual)
  
           ''Check if child has a name
  
           If Not childvisual.DependencyObjectType.Name Is Nothing OrElse Not childvisual.DependencyObjectType.Name = "" Then
  
             ''Check if child is of 'TextBox'
  
             If childvisual.DependencyObjectType.Name = "TextBox" Then
  
               Dim txtbox As TextBox = childvisual
  
               ''Update source of control
  
               If Not txtbox.GetBindingExpression(TextBox.TextProperty) Is Nothing Then txtbox.GetBindingExpression(TextBox.TextProperty).UpdateSource()
  
               ''Check if control has errors
  
               If System.Windows.Controls.Validation.GetHasError(txtbox) Then hasErrors = True
  
               'for testing, need to create a new object before use   ': st.Append(txtbox.Name & vbNewLine) : MessageBox.Show(st.ToString)
  
             End If
  
             ''Check if child is of 'ComboBox'
  
             If childvisual.DependencyObjectType.Name = "ComboBox" Then
  
               Dim combox As ComboBox = childvisual
  
               ''Update source of control --Tag
  
               If Not combox.GetBindingExpression(ComboBox.TagProperty) Is Nothing Then combox.GetBindingExpression(ComboBox.TagProperty).UpdateSource()
  
               ''Update source of control --SelectedValue
  
               If Not combox.GetBindingExpression(ComboBox.SelectedValueProperty) Is Nothing Then combox.GetBindingExpression(ComboBox.SelectedValueProperty).UpdateSource()
  
               ''Check if control has errors
  
               If System.Windows.Controls.Validation.GetHasError(combox) Then hasErrors = True
  
               'for testing, need to create a new object before use   ': st.Append(combox.Name & vbNewLine) : MessageBox.Show(st.ToString)
  
             End If
  
             ''Check if child is of 'DatePicker'
  
             If childvisual.DependencyObjectType.Name = "DatePicker" Then
  
               Dim dPicker As DatePicker = childvisual
  
               ''Update source of control
  
               If Not dPicker.GetBindingExpression(DatePicker.SelectedDateProperty) Is Nothing Then dPicker.GetBindingExpression(DatePicker.SelectedDateProperty).UpdateSource()
  
               ''Check if control has errors
  
               If System.Windows.Controls.Validation.GetHasError(dPicker) Then hasErrors = True
  
               'for testing, need to create a new object before use   ': st.Append(txtbox.Name & vbNewLine) : MessageBox.Show(st.ToString)
  
             End If
  
           End If
  
           enumVisual(childvisual)
  
         Next i
  
       Catch ex As Exception
  
         Dim resultObj As New Results
  
         resultObj.displayResult(ex)
  
       End Try
  
       Return hasErrors
  
     End Function
  
     'Private st As System.Text.StringBuilder
  
   End Class
  
   Public Class val0ApprovedRegions
  
     Inherits ValidationRule
  
     Public Overrides Function Validate(ByVal value As Object, ByVal cultureInfo As System.Globalization.CultureInfo) As System.Windows.Controls.ValidationResult
  
       Dim valChar As Char = CChar(value)
  
       If valChar = "T" Then
  
         Return New ValidationResult(False, "Approved regions must be selected.")
  
       Else
  
         Return New ValidationResult(True, Nothing)
  
       End If
  
     End Function
  
   End Class  

Microsoft Lync in C#.NET

Microsoft.Lync namespace provides great way of rolling out your own custom Lync client.

I was faced with the problem on how to provide a messaging system in an enterprise software that we were creating. Seeing how well Lync worked with all its functionallities and the ability to save history into Outlook folder, I decided to build my own Lync client.

Below are pieces of code to get going with Lync... and as you will see, I am using most of the object except to provide the user with a interactive chat window. What is being done is that user or an application can provide a message to send, and the Lync application will trigger the local Lync client installed on the computer and pass in the message.


To start, we need to check if Lync client is running on the local machine:

try

            {

                _lyncClient = LyncClient.GetClient();

                return true;

            }

            catch (ClientNotFoundException ex)

            {

                MessageBox.Show(ex.ToString());

                return false;

            }

            catch (TypeInitializationException ex)

            {

                MessageBox.Show(ex.ToString());

                return false;

            }

            catch (NotStartedByUserException ex)

            {

                MessageBox.Show(ex.ToString());

                return false;

            }

            catch (Exception ex)

            {

                MessageBox.Show(ex.ToString());

                return false;

            }


We can then wire up events and check the sign in status of the client. If the client is signed out, we can sign in the client:

if (_lyncClient != null)

            {

                _lyncClient.StateChanged += new EventHandler<ClientStateChangedEventArgs>

                (LyncClient_StateChanged);

 

                // Check if Lync is signed in

                if (_lyncClient.State != ClientState.SignedIn)

                {

                    _lyncClient.BeginSignIn(null, null, null, result =>

                    {

                        if (result.IsCompleted)

                        {

                            _lyncClient.EndSignIn(result);

                            InitializeClient(); // Setup application logic

                        }

                        else

                        {

                            MessageBox.Show("Could not sign in to Lync.");

                        }

                    }

                            , "Local user signing in" as object);

                }

                else

                {

                    // Set up ConversationManager, ContactManager, and Self objects

                    // Wire up events

                    // Subscribe to events on my contacts

                    IsLyncSignedIn = true;

                    InitializeClient();

                }

            }

 
At this point, we are good to go to grab some Lync objects:
 
//Initialize Lync client
        void InitializeClient()
        {
            if (_lyncClient == null)
                _lyncClient = Microsoft.Lync.Model.LyncClient.GetClient();
 
            _conversationManager = _lyncClient.ConversationManager;
            _contactManager = _lyncClient.ContactManager;
            _self = _lyncClient.Self;
            _automation = LyncClient.GetAutomation();
 
            try
            {
                //Load all contacts
                this.ListContacts();
            }
            catch (Exception)
            {
                throw new Exception("Initialization exception.");
            }
        }
 Not so hard, ey?
So the last item remains... how do we send a message? In this case, we want to send a message to the user that a particular order belongs to from our enterprise system, so we grab their email and plug it into our Lync client together with a message:

//Send Message to selected user
        public static void SendIM(String _selectedUser, String _messageText)
        {
            try
            {
                //if ((string)SelectedDataRow[0] != null)
                if (_selectedUser != "")
                {
                    if (_messageText != String.Empty)
                    {
                        //This is shared method need this to allow automation
                        Automation automation = LyncClient.GetAutomation();
 
                        //Add two URIs to the list of IM addresses.
                        List<string> inviteeList = new List<string>();
                        inviteeList.Add(_selectedUser);
                        //inviteeList.Add(ConfigurationManager.AppSettings["CallingUserURI"]);
                        //inviteeList.Add(ConfigurationManager.AppSettings["UserURI2"]);
 
                        //Specify IM settings.
                        Dictionary<AutomationModalitySettings, object> mSettings = new Dictionary<AutomationModalitySettings, object>();
                        string messageText = _messageText;
                        mSettings.Add(AutomationModalitySettings.FirstInstantMessage, messageText);
                        mSettings.Add(AutomationModalitySettings.SendFirstInstantMessageImmediately, true);
 
                        //Broadcast the IM messages.
                        IAsyncResult ar = automation.BeginStartConversation(AutomationModalities.InstantMessage, inviteeList, mSettings, null, null);
                        csWindow = automation.EndStartConversation(ar);
                        //AutoResetEvent completedEvent = new AutoResetEvent(false);
                        //completedEvent.WaitOne();
                        //completedEvent.Set();
                    }
                    else
                    {
                        MessageBox.Show("You must enter a message");
                    }
                }
                else
                {
                    MessageBox.Show("You must enter a valid email");
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Exception");
            }
        }
 
Thats it.
Remember that this is only part of the fun. You can implement almost all the features of Lync into your custom application such as screen sharing, file transfer and more...

RelayCommand Class for MVVM - C# and VB

Publishing both C# and VB version of the RelayCommand by Josh Smith


Namespace ApplicationClass

''' <summary>

''' A command whose sole purpose is to

''' relay its functionality to other

''' objects by invoking delegates. The

''' default return value for the CanExecute

''' method is 'true'.

''' </summary>

''' <remarks>Class taken from online example. http://msdn.microsoft.com/en-us/magazine/dd419663.aspx Josh Smith</remarks>

Public Class RelayCommand

Implements ICommand

#Region "Fields"

Private ReadOnly _execute As Action(Of Object)

Private ReadOnly _canExecute As Predicate(Of Object)

#End Region

#Region "Constructors"

''' <summary>

''' Creates a new command that can always execute.

''' </summary>

''' <param name="execute">The execution logic.</param>

Public Sub New(ByVal execute As Action(Of Object))

Me.New(execute, Nothing)

End Sub

''' <summary>

''' Creates a new command.

''' </summary>

''' <param name="execute">The execution logic.</param>

''' <param name="canExecute">The execution status logic.</param>

Public Sub New(ByVal execute As Action(Of Object), ByVal canExecute As Predicate(Of Object))

If execute Is Nothing Then

Throw New ArgumentNullException("execute")

End If

_execute = execute

_canExecute = canExecute

End Sub

#End Region

#Region "ICommand Members"

'<DebuggerStepThrough()> _

Public Function CanExecute(ByVal parameter As Object) As Boolean Implements ICommand.CanExecute

Return If(_canExecute Is Nothing, True, _canExecute(parameter))

End Function

Public Custom Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged

AddHandler(ByVal value As EventHandler)

AddHandler CommandManager.RequerySuggested, value

End AddHandler

RemoveHandler(ByVal value As EventHandler)

RemoveHandler CommandManager.RequerySuggested, value

End RemoveHandler

RaiseEvent(ByVal sender As System.Object, ByVal e As System.EventArgs)

End RaiseEvent

End Event

Public Sub Execute(ByVal parameter As Object) Implements ICommand.Execute

_execute(parameter)

End Sub

#End Region

End Class

End Namespace











using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows.Input;

namespace Xpert_Lync.ViewModel

{

public class RelayCommand : ICommand

{

#region Fields

readonly Action<object> _execute;

readonly Predicate<object> _canExecute;

#endregion // Fields

#region Constructors

public RelayCommand(Action<object> execute)

: this(execute, null)

{

}

public RelayCommand(Action<object> execute, Predicate<object> canExecute)

{

if (execute == null)

throw new ArgumentNullException("execute");

_execute = execute;

_canExecute = canExecute;

}

#endregion // Constructors

#region ICommand Members

 

public bool CanExecute(object parameter)

{

return _canExecute == null ? true : _canExecute(parameter);

}

public event EventHandler CanExecuteChanged

{

add { CommandManager.RequerySuggested += value; }

remove { CommandManager.RequerySuggested -= value; }

}

public void Execute(object parameter)

{

_execute(parameter);

}

#endregion // ICommand Members

}

}