2
votes

I'm using the MVVM Light Toolkit with Silverlight.

On my UserControl I have a ListBox that displays a list of files. Each file has a delete image next to the file name. In the DataTemplate for the listbox I have an image (or can use a button) and a TextBlock.

So I want to capture using the event when the user will clicks on the image(or button with image) to remove the file from the list of files.

But I cannot seem to capture the event. Maybe this is due to having the SelectedItem Event on the listbox?

public class MainViewModel : ViewModelBase
{
    #region Properties

    public const string SelectedListBoxFilePropertyName = "SelectedUploadFile";
    private UploadFile _selectedUploadFile = null;
    public UploadFile SelectedUploadFile 
    { 
        get 
        { 
            return _selectedUploadFile;
        } 
        set
        {
            if (_selectedUploadFile == value)
                return;

            _selectedUploadFile = value;

            RaisePropertyChanged(SelectedListBoxFilePropertyName);
        }
    }

    public const string UploadFilesPropertyName = "UploadFiles";
    private ObservableCollection<UploadFile> _uploadFiles = new ObservableCollection<UploadFile>();
    public ObservableCollection<UploadFile> UploadFiles
    {
        get
        {
            return _uploadFiles;
        }
        set
        {
            if (_uploadFiles == value)
                return;

            _uploadFiles = value;

            RaisePropertyChanged(UploadFilesPropertyName);
        }
    }
    #endregion

    public static ICommand BrowseCommand { get; private set; }
    public static ICommand DragDropFileCommand { get; private set; }
    public static ICommand RemoveCommand { get; private set; }

    #region Constructor
    public MainViewModel()
    {            
        if (IsInDesignMode)
        {
            // Code runs in Blend --> create design time data.
            UploadFiles = new UploadFileContainer().UploadFiles;
        }
        else
        {
            // Code runs "for real"
        }

        WireUpCommands();
    }
    #endregion

    #region Event Handlers
    private void OnBrowseFileCommand()
    {
        var dialog = new OpenFileDialog();
        dialog.ShowDialog();

        if (dialog.Files != null)
            AddFiles(dialog.Files);
    }

    private void OnDropFileCommand(DragEventArgs e)
    {
        var files = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];

        AddFiles(files);
    }

    private void OnRemoveFileCommand()
    {
        UploadFiles.Remove(_selectedUploadFile);
    }
    #endregion

    #region Private Methods

    private void WireUpCommands()
    {
        BrowseCommand = new RelayCommand(OnBrowseFileCommand);
        DragDropFileCommand = new RelayCommand<DragEventArgs>(e => OnDropFileCommand(e));
        RemoveCommand = new RelayCommand(OnRemoveFileCommand);
        UploadCommand = new RelayCommand(OnClickUploadCommand);
    }
    #endregion
}
<ListBox Grid.Row="1" Height="214" HorizontalAlignment="Left" AllowDrop="True" Margin="6,26,0,0" Name="UploadFilesListBox" VerticalAlignment="Top" Width="415" ItemsSource="{Binding Path=UploadFiles}" SelectedItem="{Binding Path=SelectedListBoxFile, Mode=TwoWay}" ScrollViewer.VerticalScrollBarVisibility="Auto">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Drop">
            <cmd:EventToCommand Command="{Binding DragDropFileCommand}" PassEventArgsToCommand="True"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <ListBox.Background>
        <ImageBrush ImageSource="/FileUploadApplication;component/Resources/dragdrophere.png" Stretch="None" />
    </ListBox.Background>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Button Command="{Binding RemoveCommand}">                                   
                                <Image Source="/FileUploadApplication;component/Resources/delete.png"/>
                            </Button>
                            <Image Source="/FileUploadApplication;component/Resources/delete.png">
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="Click">
                                        <cmd:EventToCommand Command="{Binding RemoveCommand}"/>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </Image> <TextBlock Text=" " />
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
2
You don't to use EventToCommand for a button. Can you post your viewmodel(s)? - Derek Beattie
pretty new to mvvm and silverlight, so presumed you could not bind a repeated control on a listbox to a command, instead i figured i could use the eventtocommand. i would ideally like it to be just an image of an X instead of using the button, but not sure how to implement the click of an image. is the eventtocommand the right pattern for this? - BBurke
You can get rid of the button and use EventToCommand to trap the click event on the image, so yes it's the right pattern. If you want to use the button you can set the command property to RemoveCommand. - Derek Beattie
i was unable to get the click event to work with the image. so i used <i:EventTrigger EventName="MouseLeftButtonUp"> instead and it works perfect... Cheers Derek for the advice - BBurke

2 Answers

0
votes

Since your ItemsSource is UploadFiles it's probably sending the event to UploadFile and not the view model the user control is bound to.

0
votes

Your button is the element of the ItemTemplate. you're binding the listbox ItemsSource to the ObservableCollection. Every Itemtemplate DataContext is no MainViewModel, but UploadFile, which has no RemoveCommand. I was solving this by adding to every item the parent object using constructor. RemoveCommand was inside the item's ViewModel and insede the remove function i was calling the parent's method to delete the item. Not sure if that's the best solution but it worked for me.