0
votes

The button click does not fire if I use the DelegateCommand from Prism. If I write a command class for button click and not use Prism, then it works. This is my code with Prism:

This is my View XAML:

<Window x:Class="MVVMPractice2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Label Content="Customer Name" HorizontalAlignment="Left" Margin="0,0,0,292.8"></Label>
        <Label Name="lblName"  HorizontalAlignment="Left" Margin="108,0,0,292.8" Width="37" Content="{Binding TxtCustomerName}"></Label>

        <Label Content="Sales Amount" HorizontalAlignment="Left" Margin="0,28,0,264.8"></Label>
        <TextBox Name="lblAmount"  HorizontalAlignment="Left" Margin="101,28,0,264.8" Width="44" Text="{Binding TxtAmount}"></TextBox>

        <Label Content="Buying Habits" HorizontalAlignment="Left" Margin="0,56,0,236.8"></Label>
        <Label Name="lblBuyingHabits" HorizontalAlignment="Left" Margin="108,56,0,236.8" Width="52" Background="{Binding LblAmountColor}"></Label>

        <Label Content="Married" HorizontalAlignment="Left" Margin="0,84,0,208.8" Width="62"></Label>
        <CheckBox Name="chkMarried" HorizontalAlignment="Left" Margin="102,84,0,208.8" IsChecked="{Binding IsMarried}"></CheckBox>

        <Label Content="Tax" HorizontalAlignment="Left" Margin="0,112,0,180.8"></Label>
        <TextBlock Name="lblTax" HorizontalAlignment="Left" Margin="108,117,0,175.8" Width="37" Text="{Binding TaxAmount}"></TextBlock>

        <Button Name="btnTax" Content="Calculate Tax" Margin="118,158,287.4,123.8" Command="{Binding UpdateCommand}"></Button>

    </Grid>
</Window>

And the ViewModel:

public class MainWindowViewModel : BindableBase 
{
    //instantiate the model
    private Customer customer = new Customer();

    //property for button click command
    private DelegateCommand UpdateCommand;

    //constructor to instantiate the buttons click command
    public MainWindowViewModel()
    {
        UpdateCommand = new DelegateCommand(customer.CalculateTax, customer.IsValid);

    }

    //this property maps customer name from model to the view
    public string TxtCustomerName
    {
        get { return customer.CustomerName; }
        set { customer.CustomerName = value; }
    }

    //this property maps amount from model to the view
    public string TxtAmount
    {
        get { return Convert.ToString(customer.Amount); }
        set { customer.Amount = Convert.ToDouble(value); }
    }


    //this property maps and transforms color from model to the view
    public string LblAmountColor
    {
        get
        {
            if (customer.Amount > 2000)
            {
                return "Blue";
            }
            else if (customer.Amount > 1500)
            {
                return "Red";
            }
            return "Yellow";
        }
    }

    //this property maps and transforms married from model to the view
    public bool IsMarried
    {
        get
        {
            if (customer.Married == "Married")
            {
                return true;
            }
            else if (customer.Married == "UnMarried")
            {
                return false;
            }

            return false;
        }

        set 
        {
            if (value)
            {
                customer.Married = "Married";
            }
            else
            {
                customer.Married = "UnMarried";
            }
        }
    }

    //this property maps tax from model to the view
    public string TaxAmount
    {
        get { return Convert.ToString(customer.Tax); }
        set { customer.Tax = Convert.ToDouble(value); }


    }
}

and the Model:

public class Customer
{
    //model property
    private string customerName = "Ivan";
    public string CustomerName 
    {
        get { return customerName; }
        set { customerName = value; }
    }

    //model property
    private double amount = 2000;
    public double Amount
    {
        get { return amount; }
        set { amount = value; }
    }

    //model property
    private string married = "Married";
    public string Married
    {
        get { return married; }
        set { married = value; }
    }

    //model property
    private double tax;
    public double Tax
    {
        get { return tax; }
        set { tax = value; }

    }

    //this modifier calculates the tax
    public void CalculateTax()
    {
        if (amount > 2000)
        {
            tax = 20;
        }
        else if (amount > 1000)
        {
            tax = 10;
        }
        else
        {
            tax = 5;
        }
    }

    //this modifier validates the amount
    public bool IsValid()
    {
        if (amount < 0)
        {
            return false;
        }
        else
        {
            return true;
        }
    }
}
1
Have you tried changing the access modifier from private to public on the UpdateCommand property?R. Richards
Yes, I also tried with public but no difference.Ivan
Databinding works on properties, not on fields. Are you missing a { get; } to change the UpdateCommand field to an read only auto property? Should be at least internal, too...Haukinger
Yes, that worked. I can see it going through those methods in Calculate class. However, the value does not get updated in the UIIvan
Of course, it doesn't, why should it? I don't see anyone firing PropertyChanged :-) You probably want to do this in the execution callback passed into the UpdateCommand, or, with more boilerplate code, make Customer implement INotifyPropertyChanged and pass the update events on.Haukinger

1 Answers

2
votes

As pointed to in the comment above, changing the field to a property helps, and firing NotifyPropertyChanged (removed irrelevant parts):

public class MainWindowViewModel : BindableBase 
{
    //property for button click command
    public DelegateCommand UpdateCommand { get; }

    //constructor to instantiate the buttons click command
    public MainWindowViewModel()
    {
        UpdateCommand = new DelegateCommand(() => {
           customer.CalculateTax();
           OnPropertyChanged( () => TaxAmount );
        }, customer.IsValid);
    }

    //this property maps tax from model to the view
    public string TaxAmount
    {
        get { return Convert.ToString(customer.Tax); }
        set { customer.Tax = Convert.ToDouble(value); }
    }
}

Alternatively, make Customer implement INotifyPropertyChanged and use something like PropertyObserver to pass the events to the view.