1

New to MVVM and I'm trying to understand how I can bind commands to controls contained in a data template. This is what my XAML currently looks like:

<UserControl>
<Grid>
    <ListBox Grid.Row="1" x:Name="listBox1" ItemsSource="{Binding MyObservableCollection}" SelectionMode="Single">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <ListBoxItem>
                    <ListBoxItem.ContextMenu>
                        <ContextMenu>
                            <MenuItem Header="Apply"/>
                        </ContextMenu>
                    </ListBoxItem.ContextMenu>
                    <Imagin.Controls:Thumbnail Source="{Binding ImageSource}"/>
                </ListBoxItem>
            </DataTemplate>
        </ListBox.ItemTemplate>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal" VerticalAlignment="Center" IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                <Setter Property="VerticalContentAlignment" Value="Center" />
                <Setter Property="VerticalAlignment" Value="Center" />
                <Setter Property="Margin" Value="1,0" />
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>
</Grid>

To be clear, I am able to bind my observable collection to the ListBox just fine using my view model. I have a view model class that looks something like this:

using System;
using System.Collections.ObjectModel;
using System.Windows.Media;
using System.Drawing;
using Imagin.Imaging;
using System.Collections.Generic;

namespace MyViewModelNameSpace
{
    public class MyObject
    {
        private string name = "";
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        private ImageSource imageSource = null;
        public ImageSource ImageSource
        {
            get
            {
                return imageSource;
            }
            set
            {
                imageSource = value;
            }
        }

        public MyObject()
        {

        }
        public MyObject(string Name, ImageSource ImageSource)
        {
            this.Name = Name;
            this.ImageSource = ImageSource;
        }
    }

    public class MyViewModel : ASimplerViewModel
    {
        public MyViewModel(MainWindowViewModel mainWindowViewModel)
        {
            if (mainWindowViewModel == null)
            {
                throw new ArgumentNullException("mainWindowViewModel");
            }

            this.MainWindowViewModel = mainWindowViewModel;
        }

        private MainWindowViewModel MainWindowViewModel
        {
            get;
            set;
        }

        private ObservableCollection<MyObject> myObservableCollection = new ObservableCollection<MyObject>();
        public ObservableCollection<MyObject> MyObservableCollection
        {
            get
            {
                return myObservableCollection;
            }
            set
            {
                myObservableCollection = value;
            }
        }

    }
}

I've tried binding commands this way:

<ListBox MouseDown="SomeMouseDownEvent">

But I don't know where to define the event? I've also tried:

<ListBox MouseDown="{Binding SomeEventInMyViewModelClass}">

But I get an error saying you can't bind events this way.

How do you appropriately define commands and bind them to objects in a data template using MVVM?

1 Answers1

0

MouseDown is a RoutedEvent and hence it expects a RoutedEventHandler. Commands are supported only by those controls that implement ICommandSource and the controls expose it as Command property. You need Windows.Interactivity.dll .It has EventTriggers which helps to attach Command to any RoutedEvent.

Betson Roy
  • 131
  • 6
  • I managed to find a simpler way, actually, by adding an EventSetter to the ItemContainerStyle. Upvoted this because it works just as well. Thanks! –  Mar 02 '16 at 01:31