Question

I have the following button in my view Home.xaml. I have it binding to a property called StartStopLabel. I have implemented the interface ICommand in the same view and I could able to change the label to text "Stop" after clicking on Start(which is the initial status which I am setting in the constructor of the view as this.StartStopLabel="Start",this.ButtonStatus="click on start button"), but I am not able to do the reverse that is changing the label of button from "Stop" to "Start" .What I mean to say is ICommand is not notified of the click event when the button label shows "Stop".

Once user clicks on the "stop" button(i.e. when the button label shows the text "stop" ) I want to change the text of the textblock "BtnSTatus" to "You have clicked on start button" and back to "Click on Start button" when the button label again shows text "Start".

Any suggestions how to fix these two issues?

My View:

<Button  Name="btnStartStop" Content="{Binding StartStopLabel}"  Command="{Binding ClickCommand}"  />
 <TextBlock Name="BtnStatus" Content="{Binding ButtonStatus}">

View.Cs code:

    private string _startStopLabel;
    public string StartStopLabel
    {
        get
        {
            return _startStopLabel;
        }
        set
        {                
            _startStopLabel =  value;                
            RaisePropertyChanged("StartStopLabel");
        }
    } 

    private string _ButtonStatus;
    public string ButtonStatus
    {
        get
        {
            return _ButtonStatus;
        }
        set
        {                
            _ButtonStatus =  value;                
            RaisePropertyChanged("ButtonStatus");
        }
    } 

ClickCommand event which is part of ICommand implementation in View.cs:

  public System.Windows.Input.ICommand ClickCommand
    {
        get
        {
            return new DelegateCommand((o) =>
            {
                this.StartStopLabel = "Stop";
                Task.Factory.StartNew(() =>
                {
                    //call service on a background thread here...

                });
            });
        }
    }
Was it helpful?

Solution

Your problem is in the

public System.Windows.Input.ICommand ClickCommand
{
    get
    {
        return new DelegateCommand(....

basically every time that property gets evaluated you will have a new command being generated. So your command that you are bound to won't be the same one that you are changing the state of.

Change your implementation to create the command in advance and return the same one.

private System.Windows.Input.ICommand _clickCommand = new DelegateCommand((o) =>
        {
            this.StartStopLabel = "Stop";
            Task.Factory.StartNew(() =>
            {
                //call service on a background thread here...

            });
        });
public System.Windows.Input.ICommand ClickCommand { get { return _clickCommand; }}

In addition you will commonly see the pattern of creating the _clickCommand as a Lazy<ICommand> so that it only gets created on first usage.

OTHER TIPS

I'd propose to change the ClickCommand property so that it returns different commands for start and stop with different texts:

  1. ClickCommand is initialized with Start command.
  2. User executes command.
  3. Actions for start are executed through ICommand.Execute.
  4. ClickCommand is changed to return Stop command. OnPropertyChanged is raised for ClickCommand so that the UI binds to the new command.
  5. User executes command.
  6. Actions for stop are executed through ICommand.Execute.
  7. ClickCommand is changed to return Start command. OnPropertyChanged is raised for ClickCommand so that the UI binds to the new command. ...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top