Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bind command in WPF using MVVM

Tags:

c#

.net

mvvm

wpf

I am learning MVVM and WPF. I have a xaml file in my project and which has a simple click event handler in the code behind.

Now I want to do the same in MVVM. I read a lot of articles and also read many answers in sof. But still unable to do this.

Can anyone please give a simple example in which a button click event is done in MVVM.

Edit

<Window x:Class="WhiteBalance.BaseCalWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:uc="clr-namespace:NumberUpDownControl;assembly=NumberUpDownControl"
        xmlns:viewn="clr-namespace:WhiteBalance.ViewModels"
        Title="RefImgSettingWindow"  Height="900" Width="1000" ResizeMode="NoResize" 
        BorderThickness="4">
    <Window.Resources>
        <viewn:DashBoardViewModel x:Key="demokey"></viewn:DashBoardViewModel>
    </Window.Resources>
    <Grid x:Name="gdParent" DataContext="{StaticResource demokey}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="490" />
            <ColumnDefinition Width="488*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="300" />
            <RowDefinition Height="300" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" Grid.Column="0">
            <Label Content="{Binding Path=NAME,Mode=TwoWay}" Height="28" Name="lblTest" />
            <Button Content="Capture" Height="23" Name="btnCapture" Width="75" Command="{Binding Path=SaveCommand}"
                             Canvas.Left="94" Canvas.Top="254" />

        </StackPanel>
    </Grid>
</Window>

namespace WhiteBalance.ViewModels
{
    public class DashBoardViewModel: ObservableObject
    {
        private string _name = "dsqdasd";

        public string NAME
        {
            get { return _name; }
            set { _name = value; }
        }

        public ICommand SaveCommand
        {
            get;
            set;
        }

        private bool CanExecuteSaveCommand()
        {
            return true;    // !string.IsNullOrEmpty(LastName);
        }

        private void CreateSaveCommand()
        {
            SaveCommand = new RelayCommand(SaveExecute, CanExecuteSaveCommand);
        }

        public void SaveExecute()
        {
            //Person.Save(_newPerson);
            NAME = "Changed Name";
        }

        public DashBoardViewModel()
        {
            //objModel.TestText = "This will change";
            NAME = "TestName";
        }
    }
}

Thanks in advance.

like image 499
Narendra Avatar asked May 01 '13 08:05

Narendra


People also ask

How do you pass a command parameter in WPF MVVM?

Passing a parameter to the CanExecute and Execute methods A parameter can be passed through the "CommandParameter" property. Once the button is clicked the selected address value is passed to the ICommand. Execute method. The CommandParameter is sent to both CanExecute and Execute events.

What is command binding in WPF?

The command is the action to be executed. The command source is the object which invokes the command. The command target is the object that the command is being executed on. The command binding is the object which maps the command logic to the command.

What is MVVM command?

Commands are an implementation of the ICommand interface that is part of the . NET Framework. This interface is used a lot in MVVM applications, but it is useful not only in XAML-based apps.

What is binding in MVVM?

Compared to MVP, MVVM decouples the View from the ViewModel by using something called a Binder. The ViewModel doesn't know about the View or Views subscribed for changes. The Binder delivers the changes from the ViewModel to the View.


2 Answers

You can bind the Command property of the button to any property that returns ICommand. Prism implements a nice convenient command called DelegateCommand that is very easy to use (here is a knock-off of it):

public ICommand MyButtonClickCommand 
{
    get { return new DelegateCommand<object>(FuncToCall, FuncToEvaluate); }
}

private void FuncToCall(object context)
{
    //this is called when the button is clicked
}

private bool FuncToEvaluate(object context)
{
    //this is called to evaluate whether FuncToCall can be called
    //for example you can return true or false based on some validation logic
    return true;
}



<Button x:Name="myButton" Command="{Binding MyButtonClickCommand}" />

The CodeProject example How to use Commands in WPF has a very similar example with code that you can easily work through. The previous Stack Overflow question has an example using RoutedCommands that are statically bound to: How to bind Close command to a button, and How to bind WPF button to a command in ViewModelBase? has a slightly more advanced example.

like image 154
slugster Avatar answered Sep 19 '22 13:09

slugster


Seeing a lot of answers implementing this ICommand interface, I suggest a simpler option, which is to use the built in System.Windows.Input

Here's an example:

Xaml View:

<Window
    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"
    x:Class="SomeDialog"
    SizeToContent="WidthAndHeight"
    WindowStartupLocation="CenterOwner" 
    ResizeMode="CanResizeWithGrip">

    <StackPanel>
        <Button Width="Auto" Command="{Binding ClearCommand}" Content="Clear"/>
    </StackPanel>

</Window>

View Code behind:

using System.Windows;

public partial class SomeDialog : Window
{
    public SomeDialog()
    {
        var vm = new ViewModel();
        DataContext = vm;
        CommandBindings.AddRange(vm.Commands);
        InitializeComponent();
    }
 }

View model:

using System.Windows.Input;

public class ViewModel : ViewModelBase
{
    readonly CommandBindingCollection commands = new CommandBindingCollection();

    public static RoutedUICommand ClearCommand { get; set; } = new RoutedUICommand("Clear", "ClearCommand", typeof(ErrorDialog));

    public CommandBindingCollection Commands
    {
        get
        {
            commands.Add(new CommandBinding(ClearCommand, OnClearExecuted);
            return commands;
        }
    }

    void OnClearExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        view.DialogResult = true; //Indicate things
        view.Close(); //Close the window
    }
}

Call like this:

public void OpenSomeDialog()
{
    var dialog = new SomeDialog() {Owner = Application.Current.MainWindow};
    bool? b = dialog.ShowDialog();
    if (b != null && (bool) b)
        //Do things
}

Now go dialog things.

like image 36
CookiePolicy Avatar answered Sep 19 '22 13:09

CookiePolicy