Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does this button click work in WPF MVVM?

Tags:

c#

button

mvvm

wpf

I'm starting to study about WFM MVVM pattern.

But I can't understand why this Button click works without binding any event or action.

View

<Window x:Class="WPF2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:WPF2.ViewModel"
    Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <vm:MainWindowViewModel x:Key="MainViewModel" />
    </Window.Resources>

    <Grid x:Name="LayoutRoot"
          DataContext="{Binding Source={StaticResource MainViewModel}}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,7,0,0" Name="txtID" VerticalAlignment="Top" Width="178" Text="{Binding ElementName=ListViewProducts,Path=SelectedItem.ProductId}" />
        <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,35,0,0" Name="txtName" VerticalAlignment="Top" Width="178" Text="{Binding ElementName=ListViewProducts,Path=SelectedItem.Name}" />
        <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,61,0,0" Name="txtPrice" VerticalAlignment="Top" Width="178" Text="{Binding ElementName=ListViewProducts,Path=SelectedItem.Price}" />
        <Label Content="ID" Grid.Row="1" HorizontalAlignment="Left" Margin="12,12,0,274" Name="label1" />
        <Label Content="Price" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,59,0,0" Name="label2" VerticalAlignment="Top" />
        <Label Content="Name" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,35,0,0" Name="label3" VerticalAlignment="Top" />

        <Button Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top" Width="141" Height="23" Margin="310,40,0,0" Content="Update" />

        <ListView Name="ListViewProducts" Grid.Row="1" Margin="4,109,12,23"  ItemsSource="{Binding Path=Products}"  >
            <ListView.View>
                <GridView x:Name="grdTest">
                    <GridViewColumn Header="Product ID" DisplayMemberBinding="{Binding ProductId}" Width="100"/>
                    <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="250" />
                    <GridViewColumn Header="Price" DisplayMemberBinding="{Binding Price}" Width="127" />
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

ViewModel

class MainWindowViewModel : INotifyPropertyChanged
{
    public const string ProductsPropertyName = "Products";

    private ObservableCollection<Product> _products;

    public ObservableCollection<Product> Products
    {
        get
        {
            return _products;
        }
        set
        {
            if (_products == value)
            {
                return;
            }

            _products = value;
            RaisePropertyChanged(ProductsPropertyName);
        }
    }

    public MainWindowViewModel()
    {
        _products = new ObservableCollection<Product>
        {
            new Product {ProductId=1, Name="Pro1", Price=11},
            new Product {ProductId=2, Name="Pro2", Price=12},
            new Product {ProductId=3, Name="Pro3", Price=13},
            new Product {ProductId=4, Name="Pro4", Price=14},
            new Product {ProductId=5, Name="Pro5", Price=15}
        };
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

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

    #endregion
}

I found this code from a tutorial i've read. When i click on a row from listview, the textbox values are set. And when I edit those values and click a button, the values on listview are updated.

There is no event nor command bound on the button. So how do button click update the values from listview??

like image 436
Nikko Reyes Avatar asked Aug 08 '13 03:08

Nikko Reyes


1 Answers

I know this is old but I was looking into this scenario and found my answer. First, in MVVM theory the "code-behind" shouldn't have code all the code should be in the ViewModel class. So in order to implement button click, you have this code in the ViewModel (besides the INotifyPropertyChanged implementation):

        public ICommand ButtonCommand { get; set; }

        public MainWindowViewModel()
        {
            ButtonCommand = new RelayCommand(o => MainButtonClick("MainButton"));
        }

        private void MainButtonClick(object sender)
        {
            MessageBox.Show(sender.ToString());            
        }

Using the class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace <your namespace>.ViewModels
{
    public class RelayCommand : ICommand
    {
        private readonly Action<object> _execute;
        private readonly Predicate<object> _canExecute;

        public RelayCommand(Action<object> execute, Predicate<object> canExecute = null)
        {
            if (execute == null) throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; } 
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {
            _execute(parameter ?? "<N/A>");
        }

    }
}

And in XAML:

<Window.DataContext>
    <viewModels:MainWindowViewModel />
</Window.DataContext>  <Button Content="Button"  Command="{Binding ButtonCommand}"  />
like image 142
Mariano Peinador Avatar answered Oct 01 '22 12:10

Mariano Peinador