Search code examples
wpfmvvmcommandbinding

Sending data from view to viewmodel with command binding


Question: How do send data to a view model when using command binding? So that, for example, when i click a button, it sends the "currently selected index" of a list so that it can perform an operation on that item of the list


Further Information: I'm working on a program where i have a list of shipments, and each shipment has a list of pallets. I want to make a button that will allow me to add a new pallet to the currently selected shipment. >Edit> And to through another wrench into the works, each pallet has a list of products. so not only do i need to know what shipment i'm on, but i also need to know what pallet of what shipment I'm on.

When I do a command binding, I have no idea how to send the data to the ViewModel. I would like to keep this pure MVVM so i don't want to have the ViewModel checking the view for anything.

~N


Edits: 11/04/09 - I removed the section of the question about the instantiation of the ViewModel. I'll ask that again in a different question as this one is well on track for solving the other question. And I made a few other edits to the question to clearify in the direction i want. as well as changed some grammatical bits so that it wasn't talking about two questions when there is only one.


Solution

  • I usually expose a CollectionView from the view model and set the IsSynchronizedWithCurrentItem property on the ItemsControl displaying the list in the view. Then when the command is executed, I can inspect the CollectionView.CurrrentItem propety to see what is currently selected.

    EDIT: This answer addresses the first question in your, um, question. Rather than your view sending the currently selected item to the ViewModel, the ViewModel keeps track of the currently selected item. So using this technique you don't need to work out how to send that information.

    Something like this in your view model:

    class ApplicationViewModel
    {
        // Exposes a list of ShipmentViewModels.
        public CollectionView Shipments { get; private set; }
    
        // A DelegateCommand or similar, that when executed calls AddPallet().
        public ICommand AddPalletCommand { get; private set; }
    
        void AddPallet()
        {
            ShipmentViewModel shipment = (ShipmentViewModel)Shipments.CurrentItem;
            shipment.Pallets.Add(new PalletViewModel(...));
        }
    }
    

    And then this in your xaml:

    <ListBox ItemsSource="{Binding Shipments}" IsSynchronizedWithCurrentItem="True"/>
    <Button Command="{Binding AddPalletCommand}>Add Pallet</Button>
    

    This way you can also track the selection of the Shipments collection from your ViewModel and update the command's CanExecute state.

    Does that help any?