1

Here is the working code i have: The text and background color property do change when I click the button (but for a micro second) and are then set back to the default text/color. Seems like RaisePropertyChanged is being triggered again and again. Can somebody help point what I am doing wrong?

MainWindow.xaml code

 <Window x:Class="BuiltIn_Custom_Commands_Eg.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <StackPanel HorizontalAlignment="Center">
        <TextBlock Text="{Binding txtblck_text, StringFormat=Default: {0}}" Padding="10" FontStyle="Italic" Background="{Binding txtblck_color}"/>
        <Button Content="Change Color" Width="100" Height="30" Margin="20" Command="{Binding OkCommand}" />
    </StackPanel>
</Grid>

ViewModel Code:

class Example_ViewModel : ViewModelBase
{
    #region Properties
    private string _txtblck_text;
    private Brush _txtblck_color;
    public ICommand OkCommand {get; set;}

    public string txtblck_text
    {
        get { return _txtblck_text; }
        set 
        { 
            _txtblck_text = value;
            RaisePropertyChanged("txtblck_text");
        }
    }

    public Brush txtblck_color
    {
        get { return _txtblck_color; }
        set
        {
            _txtblck_color = value;
            RaisePropertyChanged("txtblck_color");
        }
    }
    #endregion

    #region Constructor
    public Example_ViewModel()
    {
        OkCommand = new myCommand(myOkExecute, myCanOkExecute);
    }
    #endregion

    private void myOkExecute(object parameter)
    {
        txtblck_color = Brushes.CadetBlue;
        //RaisePropertyChanged("txtblck_color");

        txtblck_text = "You Clicked me!!!";
        //RaisePropertyChanged("txtblck_text");
    }

    private bool myCanOkExecute(object parameter)
    {
        txtblck_color = Brushes.Yellow;
        txtblck_text = "You havent clicked me!!!";
        return true;
    }
}
Patrick
  • 864
  • 1
  • 14
  • 27

2 Answers2

2

The CanExecute method will and should be called whenever bindings change. Therefore changing a binding in the Execute method (color) will cause CanExecute to be called again.

Instead, why dont you initialize the colors private member once in the constructor as follows.

public Example_ViewModel()
{
    OkCommand = new myCommand(myOkExecute, myCanOkExecute);
    _txtblck_color =  = Brushes.Yellow;
}

Note, the same is also true for the text property. Normally all property private member should be set up with defaults on initialize (constructor) as this avoids unnecessary calls to INotifyPropertyChanged.

Also, in order to test how the code is behaving and to confirm this just set some breakpoints in the CanExecute method to see how the program flow is behaving.

bic
  • 2,201
  • 26
  • 27
  • Thanks bic for your suggestions. Agree to have them in the constructor makes more sense so INotifyProperty doesnt call for the default settings. One quick question - when you want to customize the UI controls on loadup - is constructor always a good place or are there other places - which you recommend. Would like to try them out myself too. – Patrick Aug 20 '12 at 13:51
  • Well I suppose another area to initialize properties would be on first use. So in the property getters you can check for nulls or similar and then apply default values as needed. – bic Aug 20 '12 at 16:07
1

Your problem is that you shouldn't do any setting of your properties in your myCanOkExecute...because it is that that is being called and changing your properties back to the yellow, etc.

The CanExecute methods of Commands could be called multiple times and sometimes when you don't expect ...e.g. when the focus changes to a different control, when certain controls are being edited/sent keypress, after a Command has been executed, when someone calls CommandManager.InvalidateRequerySuggested, etc.

Thus what's happening is your myCanOkExecute is being called shortly after you have clicked and executed your button.

Colin Smith
  • 12,375
  • 4
  • 39
  • 47