MultiBinding in MVVM / Pass Multiple Parameters through Event Binding

Posted on July 5, 2019
c#
MultiBinding
MVVM
3533

I Explored myself for one casestudy as a part of learning MVVM Architecture with WPF.This article will be helpful for the participants who are in a need of passing multiple parameters to the events that are binded in viewModel. I will give u an explation of button binding event and passing multiple parameters to it through MultiBinding.

Steps to do:

If you are following the MVVM structure already,

a)create the xaml file under Views folder.

The below snippet is basically helpful if you have a single parameter to pass,

<Button Content="OK" HorizontalAlignment="Left" Margin="291,356,0,0" VerticalAlignment="Top" Width="75" Command="{Binding UpdateDB}" CommandParameter="{Binding Path=Text, ElementName=KoderName}" />
<Window x:Class="KoderPlace.Views.VehicleDetails"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:KoderPlace.Views"
        xmlns:v="clr-namespace:KoderPlace.Views"
        xmlns:converter="clr-namespace:KoderPlace.Converter" 
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:vm="clr-namespace:KoderPlace.ViewModels"
        mc:Ignorable="d"
        Title="LoginKoderPlace" Height="450" Width="800">
    <Window.Resources>
        <vm:InfoViewModel x:Key="viewModel" />
        <converter:MyValueConverter x:Key="cv" />
    </Window.Resources>
    <Grid DataContext="{StaticResource viewModel}">
        <Button Content="" />
        <TextBox IsEnabled="False" Name="KoderName" HorizontalAlignment="Left" Height="23" Margin="390,144,0,0" TextWrapping="Wrap" Text="Enter Name.." VerticalAlignment="Top" Width="120"/>
        <Label Content="Slot Number" HorizontalAlignment="Left" Margin="188,288,0,0" VerticalAlignment="Top"/>
        <Label Content="Vehicle Number" HorizontalAlignment="Left" Margin="188,202,0,0" VerticalAlignment="Top"/>
        <TextBox Name="KoderEmail" HorizontalAlignment="Left" Text="Enter Email.." Height="23" Margin="390,206,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
        <Button Content="OK" HorizontalAlignment="Left" Margin="291,356,0,0" VerticalAlignment="Top" Width="75" Command="{Binding UpdateDB}">
            <Button.CommandParameter>
                <MultiBinding Converter="{StaticResource cv}">
                    <Binding Path="Text" ElementName="KoderName"/>
                    <Binding Path="Text" ElementName="KoderEmail"/>
                </MultiBinding>
            </Button.CommandParameter>
        </Button>
    </Grid>
</Window>

If you want to pass as an array of multiple parameters i.e possible by MultiBinding control in WPF

Check the step d, to get the ViewModel.

b)If You want to pass multiple parameters to the event i.e only possible through MultiBinding.When you pass the binded parameters to the viewModel you need a converter that converts to the array. So the below code snipet is helpful to convert the results automatically.

Create a class file called MyValueConverter Under Converter folder(A folder to be created)

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace KoderPlace.Converter
{
    class MyValueConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return values.Clone();
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            return null;
        }
    }
}

 

c)The below delegate is helpful to generate the button click event. I am Writing one more class file named CommandManager under ViewModels.I will call this delegate whenever i need any action to be performed on buttons.

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

namespace KoderPlace.ViewModels
{
    public class CommandManager : ICommand
    {
        private readonly Action<object> _action;

        private readonly bool _canExecute;

        public CommandManager(Action<object> action, bool canExecute)
        {

            _action = action;
            _canExecute = canExecute;

        }

        public CommandManager(Action<object> launchTabView)
        {
            _action = launchTabView;
        }

        public void Execute(object parameter)
        {

            _action(parameter);
        }

        public bool CanExecute(object parameter)
        {

            //Console.WriteLine(parameter);
            return _canExecute;
        }


        public event EventHandler CanExecuteChanged { add { } remove { } }

    }

}

d)Create a InfoViewModel file under ViewModels folder.The MainViewModel having one button Click event i.e UpdateDB (Comes from the xaml file) and that internally calls one more method called FillSlot(through the delegate whatever defined above) have the access of getting the multiple parameters that are binded in xaml.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using KoderPlace.Models;
using KoderPlace.Views;
using System.Windows;

namespace KoderPlace.ViewModels
{
    class InfoViewModel:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyChange(string propertyName)
        {
            if (propertyName != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        
        private ICommand _UpdateDB;
        public ICommand UpdateDB
        {
            get
            {
                return new CommandManager(FillSlot, true);
            }
            set
            {
                _UpdateDB = value;
            }

        }      
       
        private void FillSlot(object obj)
        {
            string[] arr = ((IEnumerable)obj).Cast<object>()
                            .Select(x => x.ToString())
                            .ToArray();//Way of accessing multiple parameters binded in xaml
            string KoderName = arr[0];
            string KoderEmail = arr[1];   
            Console.WriteLine("Koder Name.."+KoderName+"\n"+"Koder Email.."+KoderEmail);        
        }
        
    }
   
}

 




0 comments

Please log in to leave a comment.