1

I tried to implement button click command using mvvmlight relaycommand as described on this msdn page. Basically first I implemented in VB and C# as below. As you can see codes are almost same but button click doesnt work in VB unless I create the RelayCommand in the constructor in VB and raise the PropertyChanged event in the setter of the IsInProgress property (Commented out part). Can somebody explain me this difference between VB and C#? I added a link to the test project as well. test project

XAML: (same for VB and C#)

 <Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="50" />   

    </Grid.RowDefinitions>
    <ComboBox  Grid.Column="0" Grid.Row="0"   Height="20" Margin="20,50,20,0" ItemsSource="{Binding Path=Items}"  DisplayMemberPath="Name"
          IsSynchronizedWithCurrentItem="True"
              SelectedItem="{Binding SelectedItem}" />
    <Button  Grid.Column="0" Grid.Row="1" Content="Update" Height="20" Margin="20,0" VerticalAlignment="Center" Command="{Binding UpdateClick}"  />

</Grid>

VB view Model:

Public Class MainViewModel
    Inherits NotifyUIBase

    Private _IsInProgress As Boolean

    Public Property IsInProgress() As Boolean
        Get
            Return _IsInProgress
        End Get
        Set(ByVal value As Boolean)
            _IsInProgress = value

            'RaisePropertyChanged("IsInProgress")

        End Set
    End Property

    Private _Items As List(Of Item)
    Public Property Items() As List(Of Item)
        Get
            Return _Items
        End Get
        Set(ByVal value As List(Of Item))
            _Items = value
        End Set
    End Property

    Private _selectedItem As Item
    Public Property SelectedItem() As Item
        Get
            Return _selectedItem
        End Get
        Set(ByVal value As Item)
            _selectedItem = value
        End Set
    End Property


    Public Sub New()
        _IsInProgress = False
        GetData()

        '_UpdateClick = New RelayCommand(Async Sub()
        '                                    If IsInProgress = True Then
        '                                        Exit Sub
        '                                    End If

        '                                    IsInProgress = True
        '                                    UpdateClick.RaiseCanExecuteChanged()
        '                                    Await Update(False)

        '                                    IsInProgress = False
        '                                    UpdateClick.RaiseCanExecuteChanged()
        '                                End Sub, Function() Not IsInProgress)
    End Sub

    Private _UpdateClick As RelayCommand
    Public ReadOnly Property UpdateClick() As RelayCommand
        Get


            Return If(_UpdateClick Is Nothing, New RelayCommand(Async Sub()
                                                                    If IsInProgress = True Then
                                                                        Exit Sub
                                                                    End If

                                                                    IsInProgress = True
                                                                    UpdateClick.RaiseCanExecuteChanged()
                                                                    Await Update(False)

                                                                    IsInProgress = False
                                                                    UpdateClick.RaiseCanExecuteChanged()
                                                                End Sub, Function() Not IsInProgress), _UpdateClick)


        End Get

    End Property


    Private Sub GetData()
        _Items = New List(Of Item)
        _Items.Add(New Item With {.Name = "item1", .Value = "0"})
        _Items.Add(New Item With {.Name = "item2", .Value = "1"})
        RaisePropertyChanged("Items")
    End Sub


    Private Function Update(v As Boolean) As Task(Of Boolean)
        Throw New NotImplementedException()
    End Function
End Class

C# view Model

    namespace testWPF
{
   public  class MainViewModel :NotifyUIBase
    {
        public bool IsinProgress { get; set; }
        public MainViewModel()
        {
            IsinProgress = false;
            GetData();
        }

        public List<Item> Items { get; set; }

        public Item SelectedItem { get; set; }

        private RelayCommand  _UpdateClick;

        public  RelayCommand UpdateClick
        {

            get
            {

                return _UpdateClick
                  ?? (_UpdateClick = new RelayCommand(
                    async () =>
                    {
                        if (IsinProgress )
                        {
                            return;
                        }

                        IsinProgress  = true;
                        UpdateClick.RaiseCanExecuteChanged();

                        await Update();

                        IsinProgress  = false;
                        UpdateClick.RaiseCanExecuteChanged();
                    },
                    () => !IsinProgress ));
            }

        }

        private Task<bool> Update()
        {
            throw new NotImplementedException();
        }

        private void GetData()
        {
            Items = new List<Item>();
            Items.Add(new Item
            {
                Name = "item1",
                Value = "0"
            });
            Items.Add(new Item
            {
                Name = "item2",
                Value = "1"
            });
            RaisePropertyChanged("Items");
        }

    }
}

Code behind of the XAML:

C#

 public MainWindow()
 {
    InitializeComponent();
     this.DataContext = new  MainViewModel();
 }

VB

Public Class MainWindow

    Public Sub New()


        InitializeComponent()
        Me.DataContext = New MainViewModel()


    End Sub

End Class
Emil
  • 6,411
  • 7
  • 62
  • 112
  • I would avoid complex logic in property getters, and I'd just initialize commands in constructor (or a separate method called from constructor). (http://stackoverflow.com/questions/3433899/mvvm-light-relaycommand-define-it-lazy-or-in-constructor) – mechanic Jul 08 '16 at 15:48
  • I agree there are better ways to implement the above, but I can't find anything fundamentally wrong with it. When I run the code you posted (after making the changes necessary so that it would compile), it works fine for me. That's in spite of the fact that your VB.NET code fails to set the `_UpdateClick` variable in the property getter. I do note that you didn't post anything showing where you set the view model. Are you sure you remembered to do that? Please provide a good [mcve] that reliably reproduces the problem. – Peter Duniho Jul 08 '16 at 16:22
  • @PeterDuniho I set the viewmodel in the constructor of the View. See my Edited post again please. I have also a link to download test project there. Maybe you have missed that. – Emil Jul 08 '16 at 16:30
  • Stack Overflow questions need to be _entirely_ self-contained. The above still is not. Without `RelayCommand` at a minimum, it's impossible to know whether your bug is in that class (though, given that the code you did post works, that seems likely). Also, you have not provided the `Item` class; fortunately on that point, it seems the code will compile simply by commenting out everything that refers to it. But even there, there's a remote possibility something about that class or how you use it is interfering. If you want an answer, please post a good [mcve] as requested. – Peter Duniho Jul 08 '16 at 16:42

0 Answers0