ARH
ARH

Reputation: 1716

How to call Command from MVVM binding

I have below code to bind ListBox data using MVVM. I would like to implment the Command from MVVM, data is binded completely and I don't know why it doesn't work with the Command. I don't receive the message when clicking on the button.

ViewModel

public class BookmarkViewModel : INotifyPropertyChanged
    {
        public BookmarkViewModel()
        {
            DataSource ds = new DataSource();
            deleteBookmark = new Command(executeCommand) { Enabled = true };
            _bk = ds.getBookmarkDetail();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        List<BookmarkDetail> _bk;
        public List<BookmarkDetail> Bookmarks
        {
            get { return _bk; }
            set
            {
                if (_bk != value)
                {
                    _bk = value;
                    OnPropertyChanged("Bookmarks");
                }
            }
        }

        private Command deleteBookmark;
        public Command DeleteBookmark
        {
            get
            {
                return deleteBookmark;
            }
            set
            {
                deleteBookmark = value;
            }
        }

        void executeCommand()
        {
            System.Windows.MessageBox.Show(_bk[0].SuraName);
        }


        public class Command : ICommand
        {

            private readonly Action executeAction;

            private bool enabled;
            public bool Enabled
            {
                get
                {
                    return enabled;
                }
                set
                {
                    if (enabled != value)
                    {
                        enabled = value;

                        if (CanExecuteChanged != null)
                            CanExecuteChanged(this, new EventArgs());
                    }
                }
            }

            public Command(Action executeAction)
            {
                this.executeAction = executeAction;
            }

            public bool CanExecute(object parameter)
            {
                return enabled;
            }

            public event EventHandler CanExecuteChanged;

            public void Execute(object parameter)
            {
                executeAction();
            }
        }
    }

and XAML binding

<ListBox x:Name="lsbBookmarks" FontFamily="./Fonts/ScheherazadeRegOT.ttf#Scheherazade" 
                     FlowDirection="RightToLeft" 
                     Style="{StaticResource ListBoxStyle1}"  
                     ItemsSource="{Binding Bookmarks}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel HorizontalAlignment="Stretch">
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*"></ColumnDefinition>
                                    <ColumnDefinition Width="60"></ColumnDefinition>
                                </Grid.ColumnDefinitions>
                                <StackPanel Orientation="Horizontal" Grid.Column="0"
                                                HorizontalAlignment="Stretch">
                                    <TextBlock Padding="20,0,10,0" HorizontalAlignment="Stretch">
                                                    <Run FontSize="50" Text="{Binding ArabicText.ArabicAyaNumber}"  
                                                         FontFamily="./Fonts/KPGQPC.otf#KFGQPC Uthmanic Script HAFS" 
                                                         Foreground="Blue"/> <Run FontSize="30" Text="{Binding ArabicText.Aya}"/>
                                    </TextBlock>
                                </StackPanel>
                                <Button Grid.Column="1" Tag="{Binding ArabicText.ArabicTextID}" 
                                                    VerticalAlignment="Center"
                                                    Height="60" Width="50" HorizontalAlignment="Right" 
                                                            Content="X" BorderBrush="Red" 
                                                            Background="Red" BorderThickness="0" 
                                                    Padding="0" Command="{Binding DeleteBookmark}"></Button>
                            </Grid>
                            <Line X1="0" X2="1" Y1="0" Y2="0" Stretch="Fill" VerticalAlignment="Bottom" 
                                                            StrokeThickness="1" Stroke="LightGray" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>

Any Ideas, How to implement the Command using MVVM?

Thanks!

Upvotes: 0

Views: 127

Answers (2)

Kaj
Kaj

Reputation: 333

If I were you I would:

  1. Move the Command implementation to a separate file or declare it outside the scope of the BookmarkViewModel class.
  2. Use the second option as ig2r suggested. Your binding would look like this:Command="{Binding DataContext.DeleteBookmark, ElementName=lsbBookmarks}" You can also use any other ElementName other than lsbBookmarks that's defined as a parent of the ListBox.

Upvotes: 1

ig2r
ig2r

Reputation: 2394

It appears that your DeleteBookmark command is exposed as a property on the BookmarkViewModel class, whereas the actual data context within the DataTemplate used to render individual ListBox items will be an instance of BookmarkDetail. Since BookmarkDetail does not declare a DeleteBookmark command, the binding fails.

To correct this, either:

  1. Define and expose the DeleteBookmark command on the BookmarkDetail class, or
  2. Extend your command binding to tell the binding system where to look for the delete command, e.g., Command="{Binding DataContext.DeleteBookmark, ElementName=lsbBookmarks}" (untested).

Upvotes: 0

Related Questions