2

I am working on a Win10 UWP app using MVVMLight (I've never used MVVMLight, and never done commands "properly"). I have an ItemsControl bound to an ObservableCollection. The Participant has two properties - Name and Laps. I have controls in the ItemsControl.ItemTemplate to display a button (subtract), the Name property of the item, the Laps property of the item, and another button (add). Here is the XAML:

<ItemsControl
                    ItemsSource="{Binding Participants, Mode= TwoWay}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Grid
                                MinWidth="300"
                                Margin="0, 12">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition
                                        Width="2*"></ColumnDefinition>
                                    <ColumnDefinition
                                        Width="6*"></ColumnDefinition>
                                    <ColumnDefinition
                                        Width="2*"></ColumnDefinition>
                                    <ColumnDefinition
                                        Width="3*"></ColumnDefinition>
                                </Grid.ColumnDefinitions>
                                <Button
                                    Content="&#xE108;"
                                    FontFamily="Segoe MDL2 Assets"
                                    FontSize="20"
                                    Grid.Column="0"
                                    Margin="0, 0, 12, 0"></Button>
                                <TextBlock
                                    Text="{Binding Path=Name, Mode=TwoWay}"
                                    FontSize="20"
                                    FontWeight="Bold"
                                    Grid.Column="1"></TextBlock>
                                <TextBlock
                                    Text="{Binding Laps, Mode=TwoWay}"
                                    FontSize="20"
                                    FontWeight="Bold"
                                    Grid.Column="2"></TextBlock>
                                <Button
                                    Content="&#xE710;"
                                    FontFamily="Segoe MDL2 Assets"
                                    FontSize="20"
                                    Command="{Binding AddLapCommand}"
                                    CommandParameter="{Binding}"
                                    Grid.Column="3"
                                    Margin="12, 0, 0, 0"></Button>
                            </Grid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>

The view model creates an ObservableCollection called Participants. I am trying to bind the add button (and then of course the subtract button) to a RelayCommand in the VM. I've tried a number of things, so I can't post all I've tried here. Here is the latest of what I have, (but it still doesn't work):

    public RelayCommand<object> AddLapCommand
    {
        get
        {
            if (_addLapCommand == null)
            {
                _addLapCommand = new RelayCommand<object>((e) => ExecuteAddLapCommand(e));
            }
            return _addLapCommand;
        }
    }

    private void ExecuteAddLapCommand(object o)
    {
        throw new NotImplementedException();
    }

The intellisense in the xaml tells me that it cannot resolve the property AddLapCommand in data context of type LapCounter.Model.Participant. I'm not trying to get to the Participant class, but to the HomeViewModel class, which is the DataContext of the page. I think I can see where it is getting the LapCounter.Model.Participant from, from the individual item in the collection that the ItemsControl is bound to. But I was under the impression that if a DataContext couldn't be found, it would continue up the visual tree until it found the right one. Here's the DataContext in the page declaration:

DataContext="{Binding Home, Source={StaticResource Locator}}"

How do I get it to look at the VM for the RelayCommand? What I need to do is have the button send the Participant that it represents to the RelayCommand as a parameter, and use that to increment (and decrement in the case of the subtract button) the Laps integer for that particular Participant.

I appreciate any help I can get. Thanks!

EDIT Added Participants property from the VM to show because my view is not updating. Here is the Participants property:

    /// <summary>
    /// The <see cref="Participants" /> property's name.
    /// </summary>
    public const string ParticipantsPropertyName = "Participants";

    private ObservableCollection<Participant> _participants = new ObservableCollection<Participant>();

    /// <summary>
    /// Sets and gets the Participants property.
    /// Changes to that property's value raise the PropertyChanged event. 
    /// </summary>
    public ObservableCollection<Participant> Participants
    {
        get
        {
            return _participants;
        }

        set
        {
            if (_participants == value)
            {
                return;
            }

            _participants = value;
            RaisePropertyChanged(() => Participants);
        }
    }

Thanks to Eldar Dordzhiev for his help so far!

Rich Hopkins
  • 1,861
  • 15
  • 29

1 Answers1

1

Try this:

Command="{Binding Home.AddLapCommand, Source={StaticResource Locator}}"

There's not much to explain to you as long as everything you've written is absolutely right.

As for incrementing\decrementing the Laps, you can simply pass the Participant into the command handler and alter the Laps. If you use MVVMLight that is done with RelayCommand<Participant>. Don't forget to pass the Participant in CommandParameter.

Eldar Dordzhiev
  • 5,105
  • 2
  • 22
  • 26
  • Thanks, Eldar. That solved that problem. Now my RelayCommand works, and the Laps property of the Participant is updated. Now the problem that I have is that the Laps display on the view is not being updated. I've added the code from VM of the Participants property, and it implements RaisePropertyChanged, but it isn't working. Doesn't the collection RaisePropertyChanged if an item in the collection is changed? – Rich Hopkins Apr 19 '16 at 22:05
  • Never mind - I figured it out thanks to this post (http://stackoverflow.com/questions/5285377/wpf-mvvm-inotifypropertychanged-implementation-model-or-viewmodel). It works now. Thanks so much! – Rich Hopkins Apr 19 '16 at 22:22
  • @RichHopkins You need to implement `INotifyPropertyChanged` in the `Participant` class. Please, don't forget to mark my answer as the answer if it helps you. – Eldar Dordzhiev Apr 19 '16 at 22:22