简体   繁体   中英

Change Button background color when clicked using WPF and binding

I am trying to change to color of button when clicked. It is taking the initial color assigned but not updating when clicked. I attaching my code, let me know where I am going wrong. I tried to implement the code provided in the following post

enter link description here

MainWindow.xaml snippet

<Window.Resources>
    <viewModels:MainWindowViewModel x:Key="MainViewModel"/>
</Window.Resources>

<Border Padding="20">
    <StackPanel DataContext="{Binding Source={StaticResource MainViewModel}}">
        <Button Content="Button1" Margin="10 10 10 10" Command="{Binding ClickCommand, Mode=OneWay}" Background="{Binding BackgroundColorBtn1}"/>
        <Button Content="Button2 " Margin="10 10 10 10"></Button>
    </StackPanel>
</Border>

</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainWindowViewModel();
        }

        private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
        {
            var desktopWorkingArea = System.Windows.SystemParameters.WorkArea;
            this.Left = desktopWorkingArea.Right - this.Width;
            this.Top = desktopWorkingArea.Bottom - this.Height;
        }
    }

MainWindowViewModel.cs

namespace DockedPanel.ViewModels
{
    public class MainWindowViewModel:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public MainWindowViewModel()
        {
            _canExecute = true;
        }
        private ICommand _clickCommand;
        public ICommand ClickCommand
        {
            get
            {
                return _clickCommand ?? (_clickCommand = new CommandHandler(() => MyAction(), _canExecute));
            }
        }
        private bool _canExecute;
        public void MyAction()
        {
            _backgroundColorBtn1 = Colors.Blue;
        }

        private void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private Color _backgroundColorBtn1 =  Colors.White;
        public Color BackgroundColorBtn1
        {
            get { return _backgroundColorBtn1; }
            set
            {
                if (value == _backgroundColorBtn1)
                    return;

                _backgroundColorBtn1 = value;

                OnPropertyChanged(nameof(BackgroundColorBtn1));
            }
        }
    }
}

and finally CommandHandler

namespace DockedPanel.ViewModels.Command
{
    public class CommandHandler : ICommand
    {
        private Action _action;
        private bool _canExecute;
        public CommandHandler(Action action, bool canExecute)
        {
            _action = action;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            _action();
        }
    }
}

You need to call OnPropertyChanged on the BackgroundColorBtn1 property since you are changing the private backing variable, and the View needs to be notified.

You can modify your MyAction method as following

 public void MyAction()
 {
      _backgroundColorBtn1 = Colors.Blue;
      OnPropertyChanged(nameof(BackgroundColorBtn1));
 }

Alternatively, you could set the Property directly instead of backing field, which would invoke the OnPropertyChanged call itself.

 public void MyAction()
 {
      BackgroundColorBtn1 = Colors.Blue;
 }

You would also need to use a Color To Brush Converter. The background property of button accepts Brush, not color. The convertor would allow you to convert the chosen Color to Brush.

You can define the Converter as following

public class ColorToSolidColorBrushValueConverter : IValueConverter 
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null)
            return null;

        if (value is Color)
            return new SolidColorBrush((Color)value);

        throw new InvalidOperationException("Unsupported type [" + value.GetType().Name + "], ColorToSolidColorBrushValueConverter.Convert()");
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   {
        throw new NotImplementedException();
    }
}

And then, you can use it as

Background="{Binding BackgroundColorBtn1, Converter={StaticResource colorToSolidColorBrushConverter}}"

Please ensure you have added following to your Resource section before using it

<Window.Resources>
<ResourceDictionary>
        <myNameSpace:ColorToSolidColorBrushValueConverter  x:Key="colorToSolidColorBrushConverter"/>
</ResourceDictionary>
</Window.Resources>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM