0

I'm building my first MVVM Application in WPF. On this moment I'm trying to raise an event by double clicking on a item in a listbox. This event is handled by the View as shown below in the code.

Now I want to send the ViewModel the index of the item in the listbox which is doubleclicked. How do i do that?

PS: the ClassObject and the ClassDiagram are both custom classes, they have both the same attribute "Name"

View

public partial class ProjectView : UserControl
    {
        public ProjectView()
        {
            InitializeComponent();
            this.DataContext = new ProjectViewModel();
        }

        public void listBoxProject_MouseDoubleClick(object sender,MouseButtonEventArgs e)
        {
            MessageBox.Show(listBoxProject.SelectedIndex.ToString()); //Send index to ViewModel
        }
    }

XAML

<ListBox x:Name="listBoxProject" ItemsSource="{Binding CollectionList}" HorizontalAlignment="Stretch" Margin="-1,32,-1,-1" VerticalAlignment="Stretch" Width="auto" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
            DisplayMemberPath="Name"
            SelectedValuePath="Name"
            >
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}">
            <EventSetter Event="MouseDoubleClick" Handler="listBoxProject_MouseDoubleClick"/>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

ViewModel

namespace VITUMLEditor.ViewModels
{
    public class ProjectViewModel:BaseViewModel
    {
        private readonly CompositeCollection collectionList = new CompositeCollection();

        public ICommand AddClassCommand
        {
            get { return new DelegateCommand(AddClass); }
        }

        public ICommand AddClassDiagramCommand
        {
            get { return new DelegateCommand(AddClassDiagram); }
        }

        private void AddClass()
        {
            collectionList.Add(new ClassObject("Class" + ClassObject.Key, VisibilityEnum.Public));
        }

        private void AddClassDiagram()
        {
            collectionList.Add(new ClassDiagram("ClassDiagram" + ClassDiagram.Key));
        }

        public CompositeCollection CollectionList
        {
            get { return collectionList; }
        }
    }
}
Basseytje
  • 13
  • 1
  • 10

1 Answers1

-2

In principle, you should do this with a Command. But then you've got to write code to make the double click invoke the command. The following is simple enough, and good enough for a very great number of common cases. We have dozens of these in production code and they're causing us no pain, because the view-viewmodel relationships in question are all 1:1 and will remain so. Just bear in mind that it's Impure MVVM, and can arbitrarily limit your options down the line.

Add an appropriately-named and parametered method to the viewmodel:

public void ActivateItem(object item)
{
    //  Better if these two classes share a common base class or interface with 
    //  a virtual function to be called in this case, but there I go ranting from 
    //  the pulpit again. 
    if (item is ClassObject)
    {
        //  Stuff
    }
    else if (item is ClassDiagram)
    {
        //  Other stuff
    }
}

And call it from the view:

//  This is faintly sketchy, in many people's view, because in principle 
//  a view can have any type of viewmodel that has properties of the 
//  appropriate names and types. You *could* make many viewmodels all 
//  implement some interface that supports common stuff, and make this that
//  type. That wouldn't save you from the MVVM Inquisition, but it would be
//  more flexible than this. 
protected ProjectViewModel ViewModel { get { return DataContext as ProjectViewModel; } }

public void listBoxProject_MouseDoubleClick(object sender,MouseButtonEventArgs e)
{
    //  WARNING you need to add range checking here
    var lb = sender as ListBox;
    var item = lb.Items[lb.SelectedIndex];

    ViewModel.ActivateItem(item);
}
  • Thanks! I edited the code in the Event to `ViewModel.OpenClassDiagram(listBoxProject.SelectedItem);` That did the trick – Basseytje Jun 06 '16 at 14:41