Do you need all those properties in MVVM?

I recently started using MVVM and just figured out how to work with Commands with the help of http://www.dotmaniac.net/wpf-karl-shifletts-relaycommand/ and http://www.codeproject.com/Articles/126249/MVVM-Pattern-in-WPF-A-Simple-Tutorial-for-Absolute. I succeeded to get a simple test to work.

Below here is the code I put together taken from these resources I just mentioned. So to clarify, the code I post IS WORKING. I just think it's not compact to be useful. I have an application in progress that already has all it Properties linked to TextBoxes,Labels,Buttons,DataGrids, ... but the Events if you click on a button aren't yet. Therefore the code below. The reason why I post my code is as follow:

  1. Can the code for Private _oShowMsgBox As ICommand be shorter? From the looks of it I need 2 Subs or Functions to do the same what I could do in 1.

    Private _oShowMsgBox As ICommand = New RelayCommand(New Action(Of Object)(AddressOf ShowMsgBoxSub), 
                                                        New Predicate(Of Object)(Function() If(TextboxText = "", False, True)))
    
  2. Is it necessary to have all those Properties in your file (properties for the Commands and binding data to the controls)? The application I'm working on has over 150 controls (TextBox,Label,Button,DataGrid) so the code is getting big pretty fast and looks like it's very inefficient.

Below the line is a snapshot of working code in my project. See it as a tiny part of what I have in total right now.


My xaml:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:MVVM_Test" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="MainWindow" Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:ViewModel x:Key="ViewModelDataSource" d:IsDataSource="True" />
    </Window.Resources>
    <Grid DataContext="{Binding Source={StaticResource ViewModelDataSource}}">
        <Button Content="{Binding TextboxText}" Command="{Binding ShowMsgBox}"/>
        <TextBox Text="{Binding TextboxText, UpdateSourceTrigger=PropertyChanged}" />
    </Grid>
</Window>

For the first time I also succeeded to have NO code in my code behind file.

This is the RelayCommand I came up with:

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"
Public Sub New(ByVal execute As Action(Of Object))
    Me.New(execute, Nothing)
End Sub

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"

Public Function CanExecute(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(parameter As Object) Implements ICommand.Execute
    _execute(parameter)
End Sub

#End Region

End Class

Then in my ViewModel I have this:

Imports System.ComponentModel
Imports System.Runtime.CompilerServices

Public Class ViewModel
Implements INotifyPropertyChanged

Private _sText As String
Public Property TextboxText As String
    Get
        Return _sText
    End Get
    Set(ByVal value As String)
        _sText = value
        RaisePropertyChanged()
    End Set
End Property

Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged

Protected Sub RaisePropertyChanged(<CallerMemberName()> Optional ByVal propertyName As String = Nothing)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub

Private _oShowMsgBox As ICommand = New RelayCommand(New Action(Of Object)(AddressOf ShowMsgBoxSub), New Predicate(Of Object)(Function() If(TextboxText = "", False, True)))
Public Property ShowMsgBox As ICommand
    Get
        Return _oShowMsgBox
    End Get
    Set(ByVal value As ICommand)
        _oShowMsgBox = value
    End Set
End Property

Public Sub ShowMsgBoxSub()
    MessageBox.Show(TextboxText)
End Sub

End Class

Answers


For commands, which I suspect in your case are readonly, you should be able to use VB.Net's auto property feature:

Public Property ShowMsgBox _
 As New RelayCommand( _
   New Action(Of Object)(AddressOf ShowMsgBoxSub), _
   New Predicate(Of Object)(Function() If(TextboxText = "", False, True)))

For bindable properties that change you will need to use the verbose property syntax and signal that the property has changed in the setter by firing the PropertyChanged event on your view model class that implements INotifyPropertyChanged.


Need Your Help

submit button post not sent after using javascript

javascript php forms

I have 3 separate forms each with their own submit buttons (removed all other lines of form code as not required):

http C# System.Net.WebClient authorization in rapidshare

c# http authorization webclient rapidshare

I am trying to download a file from rapidshare using System.Net.WebClient in C#.