0

How to use ICommand interface with MVVM?

In view I add DataContext (which is my ViewModel : INotifyPropertyChanged) and I bind control's property - IsInterminate of progress bar - to property of my ViewModel. This property of my ViewModel isn't static, so I need instance of ViewModel.

My questions is: how I should update this ViewModel instance (property bound to view's progress bar) in command's method (this method is of ViewModel)?

<StatusBar Grid.Row="1">
    <StatusBar.DataContext>
        <viemodel:EventsViewModel x:Name="evm"/>
    </StatusBar.DataContext>
    <Label x:Name="lbStatusLabel" Width="70" Height="40" Content="{Binding EventsCollection.Count}"/>
    <Separator />
    <ProgressBar x:Name="pbProgress" Width="300" Height="40" IsIndeterminate="{Binding Pennding}"/>
</StatusBar>

class EventsViewModel : ViewModel
{
    private static FWatch fw;
    private static string fileName;
    private static string pathToFile;
    private static string pathToDirectory;

    public EventsViewModel()
    {
        _startCommand = new RelayCommand(OpenFileCommand);
    }

    private ICommand _startCommand;
    public ICommand StartCommand
    {
        get { return _startCommand; }
    }

    private static ObservableCollection<Event> _eventsCollection = new ObservableCollection<Event>();
    public static ObservableCollection<Event> EventsCollection
    { 
        get { return _eventsCollection; }
    }

    private static string _buttonContent = "Open file";        
    public string ButtonContent
    {
        get { return _buttonContent; }
        set
        {
            _buttonContent = value;
            NotifyPropertyChanged();
        }
    }

    private bool _pending = false;
    public bool Pennding
    {
        get { return _pending; }
        set
        {
            _pending = value;
            NotifyPropertyChanged();
        }
    }

    private void OpenFileCommand()
    { 
        // Here I want to update field _pennding - is it right? Or should I delegate it?
        // Should I update `Pendding` property of `ViewModel` where is command's method or I should do it in behind-code of view?
    }
} 
pawel__86
  • 177
  • 1
  • 1
  • 11
  • yes it is correct, the OpenFileCommand is already a delegate passed to the RelayCommand, this is exactly how it should be used. One thing to note when using RelayCommand (which I guess is from MVVMlight or the original Josh Smith implementation) it should be set null when the ViewModel is disposed, hence the ViewModel should implement IDisposable, if you used DelegateCommand from MS Prism then you wouldn't need to implement IDisposable has it uses weak reference for event handlers internally – AwkwardCoder Feb 13 '15 at 11:20
  • @AwkwardCoder but how to change Pennding property in this method? – pawel__86 Feb 13 '15 at 12:10
  • as shown below by @XAML Lover – AwkwardCoder Feb 13 '15 at 13:32
  • You should have something like NotifyPropertyChanged("Pennding"); Note I have the same property name as in your code here, not "Pending". – Philip Stuyck Feb 13 '15 at 13:32
  • @AwkwardCoder but it isn't working for me. Nothing change. I think I should use x:Name on progress bars data context - this give me instance of EventViewModel. – pawel__86 Feb 13 '15 at 18:09
  • @PhilipStuyck but Ive used `protected void NotifyPropertyChanged([CallerMemberName] String propertyName = "")` so I dont have to use property name. – pawel__86 Feb 13 '15 at 18:10
  • Have you tried a debugger to check that the string being passed like that is what you expect ? – Philip Stuyck Feb 13 '15 at 18:23
  • It seems unusual to have non-static properties with static backing fields. Please check whether this is by design. By the way, the only non-static fields are `_pending` and `_startCommand`. – Sergey Vyacheslavovich Brunov May 04 '15 at 21:52

3 Answers3

0

You should set your "Pending" property from Command handler. In your case, it is OpenFileCommand.

private void OpenFileCommand()
{ 
     this.Pending = true;
}
Jawahar
  • 4,775
  • 1
  • 24
  • 47
0

You have to use some command infrastructure component. There are several available. For instance MVVM Light is a good one. Take a look here for some hints: How to use RelayCommand with the MVVM Light framework

But you will need a button on your form, and bind it to the command to trigger an action on the ViewModel.

Pending should be manipulated in the ViewModel. The binding takes care of the rest. To raise "property changed" notification I use:

this.OnPropertyChanged(() => Breedte);

i.e. the property that changes is passed in the event that eventually is raised. I don't see that in your code. You need at least something similar like above or

NotifyPropertyChanged("propertyName");

otherwise the framework does not know what changed and how to adjust the GUI.

Community
  • 1
  • 1
Philip Stuyck
  • 7,344
  • 3
  • 28
  • 39
0

OK now I know.

Using datacontext in xaml creates instances. I used dataconytext tag 3 times to I had 3 instances of my viemodel.

pawel__86
  • 177
  • 1
  • 1
  • 11